blob: b7db86acf0782c9a5afdc5cefa1c82a4c8d97b02 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000048 struct {
49 ARMCC::CondCodes Cond; // Condition for IT block.
50 unsigned Mask:4; // Condition mask for instructions.
51 // Starting at first 1 (from lsb).
52 // '1' condition as indicated in IT.
53 // '0' inverse of condition (else).
54 // Count of instructions in IT block is
55 // 4 - trailingzeroes(mask)
56
57 bool FirstCond; // Explicit flag for when we're parsing the
58 // First instruction in the IT block. It's
59 // implied in the mask, so needs special
60 // handling.
61
62 unsigned CurPosition; // Current position in parsing of IT
63 // block. In range [0,3]. Initialized
64 // according to count of instructions in block.
65 // ~0U if no active IT block.
66 } ITState;
67 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000068 void forwardITPosition() {
69 if (!inITBlock()) return;
70 // Move to the next instruction in the IT block, if there is one. If not,
71 // mark the block as done.
72 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
73 if (++ITState.CurPosition == 5 - TZ)
74 ITState.CurPosition = ~0U; // Done with the IT block after this.
75 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000076
77
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000079 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
80
81 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
83
Jim Grosbach1355cf12011-07-26 17:10:22 +000084 int tryParseRegister();
85 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000086 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000088 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000089 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
90 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
92 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
94 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000095 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveThumbFunc(SMLoc L);
97 bool parseDirectiveCode(SMLoc L);
98 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000099
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000101 bool &CarrySetting, unsigned &ProcessorIMod,
102 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000104 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000105
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 bool isThumb() const {
107 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000112 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000113 bool isThumbTwo() const {
114 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
115 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000116 bool hasV6Ops() const {
117 return STI.getFeatureBits() & ARM::HasV6Ops;
118 }
James Molloyacad68d2011-09-28 14:21:38 +0000119 bool hasV7Ops() const {
120 return STI.getFeatureBits() & ARM::HasV7Ops;
121 }
Evan Cheng32869202011-07-08 22:36:29 +0000122 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000123 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
124 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool isMClass() const {
127 return STI.getFeatureBits() & ARM::FeatureMClass;
128 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000129
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000130 /// @name Auto-generated Match Functions
131 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000132
Chris Lattner0692ee62010-09-06 19:11:01 +0000133#define GET_ASSEMBLER_HEADER
134#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000136 /// }
137
Jim Grosbach89df9962011-08-26 21:43:41 +0000138 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000143 OperandMatchResultTy parseCoprocOptionOperand(
144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000149 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000151 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
152 StringRef Op, int Low, int High);
153 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "lsl", 0, 31);
155 }
156 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
157 return parsePKHImm(O, "asr", 1, 32);
158 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000159 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000160 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000161 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000162 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000163 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000164 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000165 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000166 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000167 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000168
169 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000170 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
172 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000174 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000176 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000180 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000182 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000184 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000186 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000188 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
192 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
194 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000196 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000198 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000200 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000202 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000204 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000208 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
210 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000212
213 bool validateInstruction(MCInst &Inst,
214 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000215 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000216 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000217 bool shouldOmitCCOutOperand(StringRef Mnemonic,
218 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000220public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000221 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000222 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000223 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000224 Match_RequiresV6,
225 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000226 };
227
Evan Chengffc0e732011-07-09 05:47:46 +0000228 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000229 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000230 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000231
Evan Chengebdeeab2011-07-08 01:53:10 +0000232 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000233 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000234
235 // Not in an ITBlock to start with.
236 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 // Implementation of the MCTargetAsmParser interface:
240 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
241 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000242 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool ParseDirective(AsmToken DirectiveID);
244
Jim Grosbach47a0d522011-08-16 20:45:50 +0000245 unsigned checkTargetMatchPredicate(MCInst &Inst);
246
Jim Grosbach1355cf12011-07-26 17:10:22 +0000247 bool MatchAndEmitInstruction(SMLoc IDLoc,
248 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
249 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000250};
Jim Grosbach16c74252010-10-29 14:46:02 +0000251} // end anonymous namespace
252
Chris Lattner3a697562010-10-28 17:20:03 +0000253namespace {
254
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000255/// ARMOperand - Instances of this class represent a parsed ARM machine
256/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000257class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000258 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000259 k_CondCode,
260 k_CCOut,
261 k_ITCondMask,
262 k_CoprocNum,
263 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000264 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000265 k_Immediate,
266 k_FPImmediate,
267 k_MemBarrierOpt,
268 k_Memory,
269 k_PostIndexRegister,
270 k_MSRMask,
271 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000272 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_Register,
274 k_RegisterList,
275 k_DPRRegisterList,
276 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000277 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000278 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000279 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_ShiftedRegister,
281 k_ShiftedImmediate,
282 k_ShifterImmediate,
283 k_RotateImmediate,
284 k_BitfieldDescriptor,
285 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000286 } Kind;
287
Sean Callanan76264762010-04-02 22:27:05 +0000288 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000289 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000290
291 union {
292 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000293 ARMCC::CondCodes Val;
294 } CC;
295
296 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000297 unsigned Val;
298 } Cop;
299
300 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000301 unsigned Val;
302 } CoprocOption;
303
304 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000305 unsigned Mask:4;
306 } ITMask;
307
308 struct {
309 ARM_MB::MemBOpt Val;
310 } MBOpt;
311
312 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000313 ARM_PROC::IFlags Val;
314 } IFlags;
315
316 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000317 unsigned Val;
318 } MMask;
319
320 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000321 const char *Data;
322 unsigned Length;
323 } Tok;
324
325 struct {
326 unsigned RegNum;
327 } Reg;
328
Jim Grosbach862019c2011-10-18 23:02:30 +0000329 // A vector register list is a sequential list of 1 to 4 registers.
330 struct {
331 unsigned RegNum;
332 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000333 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000334 } VectorList;
335
Bill Wendling8155e5b2010-11-06 22:19:43 +0000336 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000337 unsigned Val;
338 } VectorIndex;
339
340 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000341 const MCExpr *Val;
342 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000343
Jim Grosbach9d390362011-10-03 23:38:36 +0000344 struct {
345 unsigned Val; // encoded 8-bit representation
346 } FPImm;
347
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000348 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000349 struct {
350 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000351 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
352 // was specified.
353 const MCConstantExpr *OffsetImm; // Offset immediate value
354 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
355 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000356 unsigned ShiftImm; // shift for OffsetReg.
357 unsigned Alignment; // 0 = no alignment specified
358 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000360 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000361
362 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000363 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000364 bool isAdd;
365 ARM_AM::ShiftOpc ShiftTy;
366 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 } PostIdxReg;
368
369 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000370 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000371 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000372 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftReg;
377 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000378 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000379 struct {
380 ARM_AM::ShiftOpc ShiftTy;
381 unsigned SrcReg;
382 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000383 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000384 struct {
385 unsigned Imm;
386 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000387 struct {
388 unsigned LSB;
389 unsigned Width;
390 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000391 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000392
Bill Wendling146018f2010-11-06 21:42:12 +0000393 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
394public:
Sean Callanan76264762010-04-02 22:27:05 +0000395 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
396 Kind = o.Kind;
397 StartLoc = o.StartLoc;
398 EndLoc = o.EndLoc;
399 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000400 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000401 CC = o.CC;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000404 ITMask = o.ITMask;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000407 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_CCOut:
410 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000411 Reg = o.Reg;
412 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_RegisterList:
414 case k_DPRRegisterList:
415 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000416 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000417 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000418 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000419 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000420 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 VectorList = o.VectorList;
422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_CoprocNum:
424 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000425 Cop = o.Cop;
426 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000427 case k_CoprocOption:
428 CoprocOption = o.CoprocOption;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000431 Imm = o.Imm;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000434 FPImm = o.FPImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000504 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach9d390362011-10-03 23:38:36 +0000508 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000510 return FPImm.Val;
511 }
512
Jim Grosbach460a9052011-10-07 23:56:00 +0000513 unsigned getVectorIndex() const {
514 assert(Kind == k_VectorIndex && "Invalid access!");
515 return VectorIndex.Val;
516 }
517
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000518 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000520 return MBOpt.Val;
521 }
522
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000523 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000525 return IFlags.Val;
526 }
527
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000528 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000530 return MMask.Val;
531 }
532
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000533 bool isCoprocNum() const { return Kind == k_CoprocNum; }
534 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000535 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000536 bool isCondCode() const { return Kind == k_CondCode; }
537 bool isCCOut() const { return Kind == k_CCOut; }
538 bool isITMask() const { return Kind == k_ITCondMask; }
539 bool isITCondCode() const { return Kind == k_CondCode; }
540 bool isImm() const { return Kind == k_Immediate; }
541 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000542 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
549 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000550 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
557 }
558 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
565 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000566 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 256;
573 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000574 bool isImm0_1() const {
575 if (Kind != k_Immediate)
576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 2;
581 }
582 bool isImm0_3() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 4;
589 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000590 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 8;
597 }
598 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 16;
605 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000606 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 32;
613 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000614 bool isImm0_63() const {
615 if (Kind != k_Immediate)
616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 64;
621 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000622 bool isImm8() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value == 8;
629 }
630 bool isImm16() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 16;
637 }
638 bool isImm32() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 32;
645 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000646 bool isShrImm8() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value > 0 && Value <= 8;
653 }
654 bool isShrImm16() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 16;
661 }
662 bool isShrImm32() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 32;
669 }
670 bool isShrImm64() const {
671 if (Kind != k_Immediate)
672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value <= 64;
677 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 bool isImm1_7() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value < 8;
685 }
686 bool isImm1_15() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 16;
693 }
694 bool isImm1_31() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 32;
701 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000702 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000703 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 17;
709 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000710 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 33;
717 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000718 bool isImm0_32() const {
719 if (Kind != k_Immediate)
720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value >= 0 && Value < 33;
725 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000726 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000727 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000734 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 // If it's not a constant expression, it'll generate a fixup and be
739 // handled later.
740 if (!CE) return true;
741 int64_t Value = CE->getValue();
742 return Value >= 0 && Value < 65536;
743 }
Jim Grosbached838482011-07-26 16:24:27 +0000744 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000745 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000746 return false;
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value <= 0xffffff;
751 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000752 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value > 0 && Value < 33;
759 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000760 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value >= 0 && Value < 32;
767 }
768 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value > 0 && Value <= 32;
775 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000776 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return ARM_AM::getSOImmVal(Value) != -1;
783 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000784 bool isARMSOImmNot() const {
785 if (Kind != k_Immediate)
786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(~Value) != -1;
791 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000792 bool isARMSOImmNeg() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(-Value) != -1;
799 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000800 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000801 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getT2SOImmVal(Value) != -1;
807 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000808 bool isT2SOImmNot() const {
809 if (Kind != k_Immediate)
810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(~Value) != -1;
815 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000816 bool isT2SOImmNeg() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(-Value) != -1;
823 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000824 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000825 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return Value == 1 || Value == 0;
831 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000832 bool isReg() const { return Kind == k_Register; }
833 bool isRegList() const { return Kind == k_RegisterList; }
834 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
835 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
836 bool isToken() const { return Kind == k_Token; }
837 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
838 bool isMemory() const { return Kind == k_Memory; }
839 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
840 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
841 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
842 bool isRotImm() const { return Kind == k_RotateImmediate; }
843 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
844 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000845 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000846 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000847 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000849 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000850 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000851 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
853 (alignOK || Memory.Alignment == 0);
854 }
855 bool isAlignedMemory() const {
856 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000857 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000858 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000860 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000861 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000862 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000865 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000866 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000867 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000868 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000869 return false;
870 // Immediate offset in range [-4095, 4095].
871 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
872 if (!CE) return false;
873 int64_t Val = CE->getValue();
874 return Val > -4096 && Val < 4096;
875 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000877 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000878 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000880 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000882 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (!Memory.OffsetImm) return true;
884 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return Val > -256 && Val < 256;
886 }
887 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000888 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000889 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000890 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
892 // Immediate offset in range [-255, 255].
893 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
894 if (!CE) return false;
895 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000896 // Special case, #-0 is INT32_MIN.
897 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000899 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000900 // If we have an immediate that's not a constant, treat it as a label
901 // reference needing a fixup. If it is a constant, it's something else
902 // and we reject it.
903 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
904 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000905 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000906 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000907 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000908 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!Memory.OffsetImm) return true;
910 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000911 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000912 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000913 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000914 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000917 return false;
918 return true;
919 }
920 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000921 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
923 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000924 return false;
925 return true;
926 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000927 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000929 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000930 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000931 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000933 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
934 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000935 return false;
936 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000937 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000938 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000940 return false;
941 return true;
942 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000943 bool isMemThumbRR() const {
944 // Thumb reg+reg addressing is simple. Just two registers, a base and
945 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000947 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000948 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000949 return isARMLowRegister(Memory.BaseRegNum) &&
950 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000951 }
952 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000953 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000954 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000955 return false;
956 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000957 if (!Memory.OffsetImm) return true;
958 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000959 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
960 }
Jim Grosbach38466302011-08-19 18:55:51 +0000961 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000963 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000964 return false;
965 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!Memory.OffsetImm) return true;
967 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000968 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
969 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000970 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000972 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000973 return false;
974 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!Memory.OffsetImm) return true;
976 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000977 return Val >= 0 && Val <= 31;
978 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000979 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000980 if (!isMemory() || Memory.OffsetRegNum != 0 ||
981 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000982 return false;
983 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!Memory.OffsetImm) return true;
985 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000986 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000987 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000988 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000989 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000990 return false;
991 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000992 if (!Memory.OffsetImm) return true;
993 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000994 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
995 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000996 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000997 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000998 return false;
999 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001000 if (!Memory.OffsetImm) return true;
1001 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001002 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1003 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001004 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001005 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001006 return false;
1007 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001008 if (!Memory.OffsetImm) return true;
1009 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001010 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001011 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001012 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001013 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001014 return false;
1015 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001018 return Val >= 0 && Val < 256;
1019 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001020 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001021 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001022 return false;
1023 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001024 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001025 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001026 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001027 }
1028 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001029 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 return false;
1031 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001032 if (!Memory.OffsetImm) return true;
1033 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001034 return (Val >= 0 && Val < 4096);
1035 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001036 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001037 // If we have an immediate that's not a constant, treat it as a label
1038 // reference needing a fixup. If it is a constant, it's something else
1039 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001040 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001041 return true;
1042
Jim Grosbach57dcb852011-10-11 17:29:55 +00001043 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001044 return false;
1045 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001046 if (!Memory.OffsetImm) return true;
1047 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001048 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001049 }
1050 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001051 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 return false;
1053 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1054 if (!CE) return false;
1055 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001056 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001057 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001058 bool isPostIdxImm8s4() const {
1059 if (Kind != k_Immediate)
1060 return false;
1061 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1062 if (!CE) return false;
1063 int64_t Val = CE->getValue();
1064 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1065 (Val == INT32_MIN);
1066 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001068 bool isMSRMask() const { return Kind == k_MSRMask; }
1069 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001070
Jim Grosbach0e387b22011-10-17 22:26:03 +00001071 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001072 bool isVecListOneD() const {
1073 if (Kind != k_VectorList) return false;
1074 return VectorList.Count == 1;
1075 }
1076
Jim Grosbach280dfad2011-10-21 18:54:25 +00001077 bool isVecListTwoD() const {
1078 if (Kind != k_VectorList) return false;
1079 return VectorList.Count == 2;
1080 }
1081
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001082 bool isVecListThreeD() const {
1083 if (Kind != k_VectorList) return false;
1084 return VectorList.Count == 3;
1085 }
1086
Jim Grosbachb6310312011-10-21 20:35:01 +00001087 bool isVecListFourD() const {
1088 if (Kind != k_VectorList) return false;
1089 return VectorList.Count == 4;
1090 }
1091
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001092 bool isVecListTwoQ() const {
1093 if (Kind != k_VectorList) return false;
1094 //FIXME: We haven't taught the parser to handle by-two register lists
1095 // yet, so don't pretend to know one.
1096 return VectorList.Count == 2 && false;
1097 }
1098
Jim Grosbach98b05a52011-11-30 01:09:44 +00001099 bool isVecListOneDAllLanes() const {
1100 if (Kind != k_VectorListAllLanes) return false;
1101 return VectorList.Count == 1;
1102 }
1103
Jim Grosbach13af2222011-11-30 18:21:25 +00001104 bool isVecListTwoDAllLanes() const {
1105 if (Kind != k_VectorListAllLanes) return false;
1106 return VectorList.Count == 2;
1107 }
1108
Jim Grosbach7636bf62011-12-02 00:35:16 +00001109 bool isVecListOneDByteIndexed() const {
1110 if (Kind != k_VectorListIndexed) return false;
1111 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1112 }
1113
Jim Grosbach460a9052011-10-07 23:56:00 +00001114 bool isVectorIndex8() const {
1115 if (Kind != k_VectorIndex) return false;
1116 return VectorIndex.Val < 8;
1117 }
1118 bool isVectorIndex16() const {
1119 if (Kind != k_VectorIndex) return false;
1120 return VectorIndex.Val < 4;
1121 }
1122 bool isVectorIndex32() const {
1123 if (Kind != k_VectorIndex) return false;
1124 return VectorIndex.Val < 2;
1125 }
1126
Jim Grosbach0e387b22011-10-17 22:26:03 +00001127 bool isNEONi8splat() const {
1128 if (Kind != k_Immediate)
1129 return false;
1130 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1131 // Must be a constant.
1132 if (!CE) return false;
1133 int64_t Value = CE->getValue();
1134 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1135 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001136 return Value >= 0 && Value < 256;
1137 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001138
Jim Grosbachea461102011-10-17 23:09:09 +00001139 bool isNEONi16splat() const {
1140 if (Kind != k_Immediate)
1141 return false;
1142 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1143 // Must be a constant.
1144 if (!CE) return false;
1145 int64_t Value = CE->getValue();
1146 // i16 value in the range [0,255] or [0x0100, 0xff00]
1147 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1148 }
1149
Jim Grosbach6248a542011-10-18 00:22:00 +00001150 bool isNEONi32splat() const {
1151 if (Kind != k_Immediate)
1152 return false;
1153 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1154 // Must be a constant.
1155 if (!CE) return false;
1156 int64_t Value = CE->getValue();
1157 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1158 return (Value >= 0 && Value < 256) ||
1159 (Value >= 0x0100 && Value <= 0xff00) ||
1160 (Value >= 0x010000 && Value <= 0xff0000) ||
1161 (Value >= 0x01000000 && Value <= 0xff000000);
1162 }
1163
1164 bool isNEONi32vmov() const {
1165 if (Kind != k_Immediate)
1166 return false;
1167 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1168 // Must be a constant.
1169 if (!CE) return false;
1170 int64_t Value = CE->getValue();
1171 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1172 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1173 return (Value >= 0 && Value < 256) ||
1174 (Value >= 0x0100 && Value <= 0xff00) ||
1175 (Value >= 0x010000 && Value <= 0xff0000) ||
1176 (Value >= 0x01000000 && Value <= 0xff000000) ||
1177 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1178 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1179 }
1180
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001181 bool isNEONi64splat() const {
1182 if (Kind != k_Immediate)
1183 return false;
1184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1185 // Must be a constant.
1186 if (!CE) return false;
1187 uint64_t Value = CE->getValue();
1188 // i64 value with each byte being either 0 or 0xff.
1189 for (unsigned i = 0; i < 8; ++i)
1190 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1191 return true;
1192 }
1193
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001194 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001195 // Add as immediates when possible. Null MCExpr = 0.
1196 if (Expr == 0)
1197 Inst.addOperand(MCOperand::CreateImm(0));
1198 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001199 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1200 else
1201 Inst.addOperand(MCOperand::CreateExpr(Expr));
1202 }
1203
Daniel Dunbar8462b302010-08-11 06:36:53 +00001204 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001205 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001206 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001207 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1208 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001209 }
1210
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001211 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1214 }
1215
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001216 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1219 }
1220
1221 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1224 }
1225
Jim Grosbach89df9962011-08-26 21:43:41 +00001226 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1229 }
1230
1231 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1234 }
1235
Jim Grosbachd67641b2010-12-06 18:21:12 +00001236 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 Inst.addOperand(MCOperand::CreateReg(getReg()));
1239 }
1240
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001241 void addRegOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 Inst.addOperand(MCOperand::CreateReg(getReg()));
1244 }
1245
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001246 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001247 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001248 assert(isRegShiftedReg() &&
1249 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001250 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1251 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001252 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001253 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001254 }
1255
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001256 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001257 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001258 assert(isRegShiftedImm() &&
1259 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001260 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001261 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001262 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001263 }
1264
Jim Grosbach580f4a92011-07-25 22:20:28 +00001265 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001266 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001267 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1268 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001269 }
1270
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001271 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001272 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001273 const SmallVectorImpl<unsigned> &RegList = getRegList();
1274 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001275 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1276 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001277 }
1278
Bill Wendling0f630752010-11-17 04:32:08 +00001279 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1280 addRegListOperands(Inst, N);
1281 }
1282
1283 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1284 addRegListOperands(Inst, N);
1285 }
1286
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001287 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 1 && "Invalid number of operands!");
1289 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1290 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1291 }
1292
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001293 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1294 assert(N == 1 && "Invalid number of operands!");
1295 // Munge the lsb/width into a bitfield mask.
1296 unsigned lsb = Bitfield.LSB;
1297 unsigned width = Bitfield.Width;
1298 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1299 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1300 (32 - (lsb + width)));
1301 Inst.addOperand(MCOperand::CreateImm(Mask));
1302 }
1303
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001304 void addImmOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
1306 addExpr(Inst, getImm());
1307 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001308
Jim Grosbach9d390362011-10-03 23:38:36 +00001309 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
1311 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1312 }
1313
Jim Grosbacha77295d2011-09-08 22:07:06 +00001314 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
1316 // FIXME: We really want to scale the value here, but the LDRD/STRD
1317 // instruction don't encode operands that way yet.
1318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1320 }
1321
Jim Grosbach72f39f82011-08-24 21:22:15 +00001322 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
1324 // The immediate is scaled by four in the encoding and is stored
1325 // in the MCInst as such. Lop off the low two bits here.
1326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1327 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1328 }
1329
1330 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
1332 // The immediate is scaled by four in the encoding and is stored
1333 // in the MCInst as such. Lop off the low two bits here.
1334 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1335 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1336 }
1337
Jim Grosbachf4943352011-07-25 23:09:14 +00001338 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 // The constant encodes as the immediate-1, and we store in the instruction
1341 // the bits as encoded, so subtract off one here.
1342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1343 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1344 }
1345
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001346 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
1348 // The constant encodes as the immediate-1, and we store in the instruction
1349 // the bits as encoded, so subtract off one here.
1350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1351 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1352 }
1353
Jim Grosbach70939ee2011-08-17 21:51:27 +00001354 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
1356 // The constant encodes as the immediate, except for 32, which encodes as
1357 // zero.
1358 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1359 unsigned Imm = CE->getValue();
1360 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1361 }
1362
Jim Grosbachf6c05252011-07-21 17:23:04 +00001363 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1366 // the instruction as well.
1367 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1368 int Val = CE->getValue();
1369 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1370 }
1371
Jim Grosbach89a63372011-10-28 22:36:30 +00001372 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 // The operand is actually a t2_so_imm, but we have its bitwise
1375 // negation in the assembly source, so twiddle it here.
1376 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1377 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1378 }
1379
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001380 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 // The operand is actually a t2_so_imm, but we have its
1383 // negation in the assembly source, so twiddle it here.
1384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1385 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1386 }
1387
Jim Grosbache70ec842011-10-28 22:50:54 +00001388 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 // The operand is actually a so_imm, but we have its bitwise
1391 // negation in the assembly source, so twiddle it here.
1392 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1393 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1394 }
1395
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001396 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 // The operand is actually a so_imm, but we have its
1399 // negation in the assembly source, so twiddle it here.
1400 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1401 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1402 }
1403
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001404 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1407 }
1408
Jim Grosbach7ce05792011-08-03 23:50:40 +00001409 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001412 }
1413
Jim Grosbach57dcb852011-10-11 17:29:55 +00001414 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 2 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1417 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1418 }
1419
Jim Grosbach7ce05792011-08-03 23:50:40 +00001420 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1421 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001422 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1423 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001424 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1425 // Special case for #-0
1426 if (Val == INT32_MIN) Val = 0;
1427 if (Val < 0) Val = -Val;
1428 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1429 } else {
1430 // For register offset, we encode the shift type and negation flag
1431 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001432 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1433 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001434 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001435 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1436 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001437 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001438 }
1439
Jim Grosbach039c2e12011-08-04 23:01:30 +00001440 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 2 && "Invalid number of operands!");
1442 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1443 assert(CE && "non-constant AM2OffsetImm operand!");
1444 int32_t Val = CE->getValue();
1445 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1446 // Special case for #-0
1447 if (Val == INT32_MIN) Val = 0;
1448 if (Val < 0) Val = -Val;
1449 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1450 Inst.addOperand(MCOperand::CreateReg(0));
1451 Inst.addOperand(MCOperand::CreateImm(Val));
1452 }
1453
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001454 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1455 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001456 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1457 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001458 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1459 // Special case for #-0
1460 if (Val == INT32_MIN) Val = 0;
1461 if (Val < 0) Val = -Val;
1462 Val = ARM_AM::getAM3Opc(AddSub, Val);
1463 } else {
1464 // For register offset, we encode the shift type and negation flag
1465 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001466 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001467 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001468 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1469 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001470 Inst.addOperand(MCOperand::CreateImm(Val));
1471 }
1472
1473 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001475 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001476 int32_t Val =
1477 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1478 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1479 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001480 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001481 }
1482
1483 // Constant offset.
1484 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1485 int32_t Val = CE->getValue();
1486 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1487 // Special case for #-0
1488 if (Val == INT32_MIN) Val = 0;
1489 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001490 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001491 Inst.addOperand(MCOperand::CreateReg(0));
1492 Inst.addOperand(MCOperand::CreateImm(Val));
1493 }
1494
Jim Grosbach7ce05792011-08-03 23:50:40 +00001495 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001497 // If we have an immediate that's not a constant, treat it as a label
1498 // reference needing a fixup. If it is a constant, it's something else
1499 // and we reject it.
1500 if (isImm()) {
1501 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1502 Inst.addOperand(MCOperand::CreateImm(0));
1503 return;
1504 }
1505
Jim Grosbach7ce05792011-08-03 23:50:40 +00001506 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001507 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001508 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1509 // Special case for #-0
1510 if (Val == INT32_MIN) Val = 0;
1511 if (Val < 0) Val = -Val;
1512 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001513 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001515 }
1516
Jim Grosbacha77295d2011-09-08 22:07:06 +00001517 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001519 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1520 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001521 Inst.addOperand(MCOperand::CreateImm(Val));
1522 }
1523
Jim Grosbachb6aed502011-09-09 18:37:27 +00001524 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 2 && "Invalid number of operands!");
1526 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001527 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1528 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001529 Inst.addOperand(MCOperand::CreateImm(Val));
1530 }
1531
Jim Grosbach7ce05792011-08-03 23:50:40 +00001532 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001534 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1535 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001536 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001537 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001538
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001539 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1540 addMemImm8OffsetOperands(Inst, N);
1541 }
1542
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001543 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001544 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001545 }
1546
1547 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 2 && "Invalid number of operands!");
1549 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001550 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001551 addExpr(Inst, getImm());
1552 Inst.addOperand(MCOperand::CreateImm(0));
1553 return;
1554 }
1555
1556 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001557 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1558 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001559 Inst.addOperand(MCOperand::CreateImm(Val));
1560 }
1561
Jim Grosbach7ce05792011-08-03 23:50:40 +00001562 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001564 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001565 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001566 addExpr(Inst, getImm());
1567 Inst.addOperand(MCOperand::CreateImm(0));
1568 return;
1569 }
1570
1571 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001572 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1573 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001574 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001575 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001576
Jim Grosbach7f739be2011-09-19 22:21:13 +00001577 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001579 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1580 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001581 }
1582
1583 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001585 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1586 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001587 }
1588
Jim Grosbach7ce05792011-08-03 23:50:40 +00001589 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001591 unsigned Val =
1592 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1593 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001594 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1595 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001596 Inst.addOperand(MCOperand::CreateImm(Val));
1597 }
1598
Jim Grosbachab899c12011-09-07 23:10:15 +00001599 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001601 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1602 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1603 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001604 }
1605
Jim Grosbach7ce05792011-08-03 23:50:40 +00001606 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001608 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1609 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001610 }
1611
Jim Grosbach60f91a32011-08-19 17:55:24 +00001612 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1613 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001614 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001616 Inst.addOperand(MCOperand::CreateImm(Val));
1617 }
1618
Jim Grosbach38466302011-08-19 18:55:51 +00001619 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1620 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001621 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1622 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001623 Inst.addOperand(MCOperand::CreateImm(Val));
1624 }
1625
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001626 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1627 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001628 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001630 Inst.addOperand(MCOperand::CreateImm(Val));
1631 }
1632
Jim Grosbachecd85892011-08-19 18:13:48 +00001633 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001635 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001637 Inst.addOperand(MCOperand::CreateImm(Val));
1638 }
1639
Jim Grosbach7ce05792011-08-03 23:50:40 +00001640 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1641 assert(N == 1 && "Invalid number of operands!");
1642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1643 assert(CE && "non-constant post-idx-imm8 operand!");
1644 int Imm = CE->getValue();
1645 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001646 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001647 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1648 Inst.addOperand(MCOperand::CreateImm(Imm));
1649 }
1650
Jim Grosbach2bd01182011-10-11 21:55:36 +00001651 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1652 assert(N == 1 && "Invalid number of operands!");
1653 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1654 assert(CE && "non-constant post-idx-imm8s4 operand!");
1655 int Imm = CE->getValue();
1656 bool isAdd = Imm >= 0;
1657 if (Imm == INT32_MIN) Imm = 0;
1658 // Immediate is scaled by 4.
1659 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1660 Inst.addOperand(MCOperand::CreateImm(Imm));
1661 }
1662
Jim Grosbach7ce05792011-08-03 23:50:40 +00001663 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
1665 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001666 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1667 }
1668
1669 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1670 assert(N == 2 && "Invalid number of operands!");
1671 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1672 // The sign, shift type, and shift amount are encoded in a single operand
1673 // using the AM2 encoding helpers.
1674 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1675 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1676 PostIdxReg.ShiftTy);
1677 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001678 }
1679
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001680 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1681 assert(N == 1 && "Invalid number of operands!");
1682 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1683 }
1684
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001685 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 1 && "Invalid number of operands!");
1687 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1688 }
1689
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001690 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001691 assert(N == 1 && "Invalid number of operands!");
1692 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1693 }
1694
Jim Grosbach7636bf62011-12-02 00:35:16 +00001695 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1696 assert(N == 2 && "Invalid number of operands!");
1697 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1698 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1699 }
1700
Jim Grosbach460a9052011-10-07 23:56:00 +00001701 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1702 assert(N == 1 && "Invalid number of operands!");
1703 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1704 }
1705
1706 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1709 }
1710
1711 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1712 assert(N == 1 && "Invalid number of operands!");
1713 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1714 }
1715
Jim Grosbach0e387b22011-10-17 22:26:03 +00001716 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 1 && "Invalid number of operands!");
1718 // The immediate encodes the type of constant as well as the value.
1719 // Mask in that this is an i8 splat.
1720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1721 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1722 }
1723
Jim Grosbachea461102011-10-17 23:09:09 +00001724 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1725 assert(N == 1 && "Invalid number of operands!");
1726 // The immediate encodes the type of constant as well as the value.
1727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1728 unsigned Value = CE->getValue();
1729 if (Value >= 256)
1730 Value = (Value >> 8) | 0xa00;
1731 else
1732 Value |= 0x800;
1733 Inst.addOperand(MCOperand::CreateImm(Value));
1734 }
1735
Jim Grosbach6248a542011-10-18 00:22:00 +00001736 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 // The immediate encodes the type of constant as well as the value.
1739 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1740 unsigned Value = CE->getValue();
1741 if (Value >= 256 && Value <= 0xff00)
1742 Value = (Value >> 8) | 0x200;
1743 else if (Value > 0xffff && Value <= 0xff0000)
1744 Value = (Value >> 16) | 0x400;
1745 else if (Value > 0xffffff)
1746 Value = (Value >> 24) | 0x600;
1747 Inst.addOperand(MCOperand::CreateImm(Value));
1748 }
1749
1750 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1751 assert(N == 1 && "Invalid number of operands!");
1752 // The immediate encodes the type of constant as well as the value.
1753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1754 unsigned Value = CE->getValue();
1755 if (Value >= 256 && Value <= 0xffff)
1756 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1757 else if (Value > 0xffff && Value <= 0xffffff)
1758 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1759 else if (Value > 0xffffff)
1760 Value = (Value >> 24) | 0x600;
1761 Inst.addOperand(MCOperand::CreateImm(Value));
1762 }
1763
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001764 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1765 assert(N == 1 && "Invalid number of operands!");
1766 // The immediate encodes the type of constant as well as the value.
1767 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1768 uint64_t Value = CE->getValue();
1769 unsigned Imm = 0;
1770 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1771 Imm |= (Value & 1) << i;
1772 }
1773 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1774 }
1775
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001776 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001777
Jim Grosbach89df9962011-08-26 21:43:41 +00001778 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001779 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001780 Op->ITMask.Mask = Mask;
1781 Op->StartLoc = S;
1782 Op->EndLoc = S;
1783 return Op;
1784 }
1785
Chris Lattner3a697562010-10-28 17:20:03 +00001786 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001787 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001788 Op->CC.Val = CC;
1789 Op->StartLoc = S;
1790 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001791 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001792 }
1793
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001794 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001795 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001796 Op->Cop.Val = CopVal;
1797 Op->StartLoc = S;
1798 Op->EndLoc = S;
1799 return Op;
1800 }
1801
1802 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001803 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001804 Op->Cop.Val = CopVal;
1805 Op->StartLoc = S;
1806 Op->EndLoc = S;
1807 return Op;
1808 }
1809
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001810 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1811 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1812 Op->Cop.Val = Val;
1813 Op->StartLoc = S;
1814 Op->EndLoc = E;
1815 return Op;
1816 }
1817
Jim Grosbachd67641b2010-12-06 18:21:12 +00001818 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001819 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001820 Op->Reg.RegNum = RegNum;
1821 Op->StartLoc = S;
1822 Op->EndLoc = S;
1823 return Op;
1824 }
1825
Chris Lattner3a697562010-10-28 17:20:03 +00001826 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001827 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001828 Op->Tok.Data = Str.data();
1829 Op->Tok.Length = Str.size();
1830 Op->StartLoc = S;
1831 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001832 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001833 }
1834
Bill Wendling50d0f582010-11-18 23:43:05 +00001835 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001836 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001837 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001838 Op->StartLoc = S;
1839 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001840 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001841 }
1842
Jim Grosbache8606dc2011-07-13 17:50:29 +00001843 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1844 unsigned SrcReg,
1845 unsigned ShiftReg,
1846 unsigned ShiftImm,
1847 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001848 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001849 Op->RegShiftedReg.ShiftTy = ShTy;
1850 Op->RegShiftedReg.SrcReg = SrcReg;
1851 Op->RegShiftedReg.ShiftReg = ShiftReg;
1852 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
Owen Anderson92a20222011-07-21 18:54:16 +00001858 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1859 unsigned SrcReg,
1860 unsigned ShiftImm,
1861 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001862 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001863 Op->RegShiftedImm.ShiftTy = ShTy;
1864 Op->RegShiftedImm.SrcReg = SrcReg;
1865 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001866 Op->StartLoc = S;
1867 Op->EndLoc = E;
1868 return Op;
1869 }
1870
Jim Grosbach580f4a92011-07-25 22:20:28 +00001871 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001872 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001873 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001874 Op->ShifterImm.isASR = isASR;
1875 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001876 Op->StartLoc = S;
1877 Op->EndLoc = E;
1878 return Op;
1879 }
1880
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001881 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001882 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001883 Op->RotImm.Imm = Imm;
1884 Op->StartLoc = S;
1885 Op->EndLoc = E;
1886 return Op;
1887 }
1888
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001889 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1890 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001892 Op->Bitfield.LSB = LSB;
1893 Op->Bitfield.Width = Width;
1894 Op->StartLoc = S;
1895 Op->EndLoc = E;
1896 return Op;
1897 }
1898
Bill Wendling7729e062010-11-09 22:44:22 +00001899 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001900 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001901 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001902 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001903
Jim Grosbachd300b942011-09-13 22:56:44 +00001904 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001905 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001906 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001907 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001908 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001909
1910 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001911 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001912 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001913 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001914 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001915 Op->StartLoc = StartLoc;
1916 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001917 return Op;
1918 }
1919
Jim Grosbach862019c2011-10-18 23:02:30 +00001920 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1921 SMLoc S, SMLoc E) {
1922 ARMOperand *Op = new ARMOperand(k_VectorList);
1923 Op->VectorList.RegNum = RegNum;
1924 Op->VectorList.Count = Count;
1925 Op->StartLoc = S;
1926 Op->EndLoc = E;
1927 return Op;
1928 }
1929
Jim Grosbach98b05a52011-11-30 01:09:44 +00001930 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1931 SMLoc S, SMLoc E) {
1932 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1933 Op->VectorList.RegNum = RegNum;
1934 Op->VectorList.Count = Count;
1935 Op->StartLoc = S;
1936 Op->EndLoc = E;
1937 return Op;
1938 }
1939
Jim Grosbach7636bf62011-12-02 00:35:16 +00001940 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1941 unsigned Index, SMLoc S, SMLoc E) {
1942 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1943 Op->VectorList.RegNum = RegNum;
1944 Op->VectorList.Count = Count;
1945 Op->VectorList.LaneIndex = Index;
1946 Op->StartLoc = S;
1947 Op->EndLoc = E;
1948 return Op;
1949 }
1950
Jim Grosbach460a9052011-10-07 23:56:00 +00001951 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1952 MCContext &Ctx) {
1953 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1954 Op->VectorIndex.Val = Idx;
1955 Op->StartLoc = S;
1956 Op->EndLoc = E;
1957 return Op;
1958 }
1959
Chris Lattner3a697562010-10-28 17:20:03 +00001960 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001961 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001962 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001963 Op->StartLoc = S;
1964 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001965 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001966 }
1967
Jim Grosbach9d390362011-10-03 23:38:36 +00001968 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001970 Op->FPImm.Val = Val;
1971 Op->StartLoc = S;
1972 Op->EndLoc = S;
1973 return Op;
1974 }
1975
Jim Grosbach7ce05792011-08-03 23:50:40 +00001976 static ARMOperand *CreateMem(unsigned BaseRegNum,
1977 const MCConstantExpr *OffsetImm,
1978 unsigned OffsetRegNum,
1979 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001980 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001981 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001982 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001983 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001984 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001985 Op->Memory.BaseRegNum = BaseRegNum;
1986 Op->Memory.OffsetImm = OffsetImm;
1987 Op->Memory.OffsetRegNum = OffsetRegNum;
1988 Op->Memory.ShiftType = ShiftType;
1989 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001990 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001991 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001992 Op->StartLoc = S;
1993 Op->EndLoc = E;
1994 return Op;
1995 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001996
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001997 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1998 ARM_AM::ShiftOpc ShiftTy,
1999 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002000 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002001 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002002 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002003 Op->PostIdxReg.isAdd = isAdd;
2004 Op->PostIdxReg.ShiftTy = ShiftTy;
2005 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002006 Op->StartLoc = S;
2007 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002008 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002009 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002010
2011 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002012 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002013 Op->MBOpt.Val = Opt;
2014 Op->StartLoc = S;
2015 Op->EndLoc = S;
2016 return Op;
2017 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002018
2019 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002020 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002021 Op->IFlags.Val = IFlags;
2022 Op->StartLoc = S;
2023 Op->EndLoc = S;
2024 return Op;
2025 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002026
2027 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002029 Op->MMask.Val = MMask;
2030 Op->StartLoc = S;
2031 Op->EndLoc = S;
2032 return Op;
2033 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002034};
2035
2036} // end anonymous namespace.
2037
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002038void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002039 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002040 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002041 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2042 << ") >";
2043 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002044 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002045 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002046 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002047 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002048 OS << "<ccout " << getReg() << ">";
2049 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002050 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002051 static const char *MaskStr[] = {
2052 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2053 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2054 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002055 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2056 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2057 break;
2058 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002059 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002060 OS << "<coprocessor number: " << getCoproc() << ">";
2061 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002062 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002063 OS << "<coprocessor register: " << getCoproc() << ">";
2064 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002065 case k_CoprocOption:
2066 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2067 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002068 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002069 OS << "<mask: " << getMSRMask() << ">";
2070 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002071 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002072 getImm()->print(OS);
2073 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002074 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002075 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2076 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002077 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002078 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002079 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002080 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002081 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002082 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002083 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2084 << PostIdxReg.RegNum;
2085 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2086 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2087 << PostIdxReg.ShiftImm;
2088 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002089 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002090 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002091 OS << "<ARM_PROC::";
2092 unsigned IFlags = getProcIFlags();
2093 for (int i=2; i >= 0; --i)
2094 if (IFlags & (1 << i))
2095 OS << ARM_PROC::IFlagsToString(1 << i);
2096 OS << ">";
2097 break;
2098 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002099 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002100 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002101 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002102 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002103 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2104 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002105 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002106 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002107 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002108 << RegShiftedReg.SrcReg << " "
2109 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2110 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002111 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002112 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002113 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002114 << RegShiftedImm.SrcReg << " "
2115 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2116 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002117 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002118 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002119 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2120 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002121 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002122 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2123 << ", width: " << Bitfield.Width << ">";
2124 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002125 case k_RegisterList:
2126 case k_DPRRegisterList:
2127 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002128 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002129
Bill Wendling5fa22a12010-11-09 23:28:44 +00002130 const SmallVectorImpl<unsigned> &RegList = getRegList();
2131 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002132 I = RegList.begin(), E = RegList.end(); I != E; ) {
2133 OS << *I;
2134 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002135 }
2136
2137 OS << ">";
2138 break;
2139 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002140 case k_VectorList:
2141 OS << "<vector_list " << VectorList.Count << " * "
2142 << VectorList.RegNum << ">";
2143 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002144 case k_VectorListAllLanes:
2145 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2146 << VectorList.RegNum << ">";
2147 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002148 case k_VectorListIndexed:
2149 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2150 << VectorList.Count << " * " << VectorList.RegNum << ">";
2151 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002152 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002153 OS << "'" << getToken() << "'";
2154 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002155 case k_VectorIndex:
2156 OS << "<vectorindex " << getVectorIndex() << ">";
2157 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002158 }
2159}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002160
2161/// @name Auto-generated Match Functions
2162/// {
2163
2164static unsigned MatchRegisterName(StringRef Name);
2165
2166/// }
2167
Bob Wilson69df7232011-02-03 21:46:10 +00002168bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2169 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002170 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002171
2172 return (RegNo == (unsigned)-1);
2173}
2174
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002175/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002176/// and if it is a register name the token is eaten and the register number is
2177/// returned. Otherwise return -1.
2178///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002179int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002180 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002181 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002182
Benjamin Kramer59085362011-11-06 20:37:06 +00002183 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002184 unsigned RegNum = MatchRegisterName(lowerCase);
2185 if (!RegNum) {
2186 RegNum = StringSwitch<unsigned>(lowerCase)
2187 .Case("r13", ARM::SP)
2188 .Case("r14", ARM::LR)
2189 .Case("r15", ARM::PC)
2190 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002191 // Additional register name aliases for 'gas' compatibility.
2192 .Case("a1", ARM::R0)
2193 .Case("a2", ARM::R1)
2194 .Case("a3", ARM::R2)
2195 .Case("a4", ARM::R3)
2196 .Case("v1", ARM::R4)
2197 .Case("v2", ARM::R5)
2198 .Case("v3", ARM::R6)
2199 .Case("v4", ARM::R7)
2200 .Case("v5", ARM::R8)
2201 .Case("v6", ARM::R9)
2202 .Case("v7", ARM::R10)
2203 .Case("v8", ARM::R11)
2204 .Case("sb", ARM::R9)
2205 .Case("sl", ARM::R10)
2206 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002207 .Default(0);
2208 }
2209 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002210
Chris Lattnere5658fa2010-10-30 04:09:10 +00002211 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002212
Chris Lattnere5658fa2010-10-30 04:09:10 +00002213 return RegNum;
2214}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002215
Jim Grosbach19906722011-07-13 18:49:30 +00002216// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2217// If a recoverable error occurs, return 1. If an irrecoverable error
2218// occurs, return -1. An irrecoverable error is one where tokens have been
2219// consumed in the process of trying to parse the shifter (i.e., when it is
2220// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002221int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002222 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2223 SMLoc S = Parser.getTok().getLoc();
2224 const AsmToken &Tok = Parser.getTok();
2225 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2226
Benjamin Kramer59085362011-11-06 20:37:06 +00002227 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002228 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002229 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002230 .Case("lsl", ARM_AM::lsl)
2231 .Case("lsr", ARM_AM::lsr)
2232 .Case("asr", ARM_AM::asr)
2233 .Case("ror", ARM_AM::ror)
2234 .Case("rrx", ARM_AM::rrx)
2235 .Default(ARM_AM::no_shift);
2236
2237 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002238 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002239
Jim Grosbache8606dc2011-07-13 17:50:29 +00002240 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002241
Jim Grosbache8606dc2011-07-13 17:50:29 +00002242 // The source register for the shift has already been added to the
2243 // operand list, so we need to pop it off and combine it into the shifted
2244 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002245 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002246 if (!PrevOp->isReg())
2247 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2248 int SrcReg = PrevOp->getReg();
2249 int64_t Imm = 0;
2250 int ShiftReg = 0;
2251 if (ShiftTy == ARM_AM::rrx) {
2252 // RRX Doesn't have an explicit shift amount. The encoder expects
2253 // the shift register to be the same as the source register. Seems odd,
2254 // but OK.
2255 ShiftReg = SrcReg;
2256 } else {
2257 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002258 if (Parser.getTok().is(AsmToken::Hash) ||
2259 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002260 Parser.Lex(); // Eat hash.
2261 SMLoc ImmLoc = Parser.getTok().getLoc();
2262 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002263 if (getParser().ParseExpression(ShiftExpr)) {
2264 Error(ImmLoc, "invalid immediate shift value");
2265 return -1;
2266 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002267 // The expression must be evaluatable as an immediate.
2268 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002269 if (!CE) {
2270 Error(ImmLoc, "invalid immediate shift value");
2271 return -1;
2272 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002273 // Range check the immediate.
2274 // lsl, ror: 0 <= imm <= 31
2275 // lsr, asr: 0 <= imm <= 32
2276 Imm = CE->getValue();
2277 if (Imm < 0 ||
2278 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2279 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002280 Error(ImmLoc, "immediate shift value out of range");
2281 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002282 }
2283 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002284 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002285 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002286 if (ShiftReg == -1) {
2287 Error (L, "expected immediate or register in shift operand");
2288 return -1;
2289 }
2290 } else {
2291 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002292 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002293 return -1;
2294 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002295 }
2296
Owen Anderson92a20222011-07-21 18:54:16 +00002297 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2298 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002299 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002300 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002301 else
2302 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2303 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002304
Jim Grosbach19906722011-07-13 18:49:30 +00002305 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002306}
2307
2308
Bill Wendling50d0f582010-11-18 23:43:05 +00002309/// Try to parse a register name. The token must be an Identifier when called.
2310/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2311/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002312///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002313/// TODO this is likely to change to allow different register types and or to
2314/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002315bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002316tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002317 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002318 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002319 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002320 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002321
Bill Wendling50d0f582010-11-18 23:43:05 +00002322 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002323
Chris Lattnere5658fa2010-10-30 04:09:10 +00002324 const AsmToken &ExclaimTok = Parser.getTok();
2325 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002326 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2327 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002328 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002329 return false;
2330 }
2331
2332 // Also check for an index operand. This is only legal for vector registers,
2333 // but that'll get caught OK in operand matching, so we don't need to
2334 // explicitly filter everything else out here.
2335 if (Parser.getTok().is(AsmToken::LBrac)) {
2336 SMLoc SIdx = Parser.getTok().getLoc();
2337 Parser.Lex(); // Eat left bracket token.
2338
2339 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002340 if (getParser().ParseExpression(ImmVal))
2341 return MatchOperand_ParseFail;
2342 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2343 if (!MCE) {
2344 TokError("immediate value expected for vector index");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 SMLoc E = Parser.getTok().getLoc();
2349 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2350 Error(E, "']' expected");
2351 return MatchOperand_ParseFail;
2352 }
2353
2354 Parser.Lex(); // Eat right bracket token.
2355
2356 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2357 SIdx, E,
2358 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002359 }
2360
Bill Wendling50d0f582010-11-18 23:43:05 +00002361 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002362}
2363
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002364/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2365/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2366/// "c5", ...
2367static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002368 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2369 // but efficient.
2370 switch (Name.size()) {
2371 default: break;
2372 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002373 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002374 return -1;
2375 switch (Name[1]) {
2376 default: return -1;
2377 case '0': return 0;
2378 case '1': return 1;
2379 case '2': return 2;
2380 case '3': return 3;
2381 case '4': return 4;
2382 case '5': return 5;
2383 case '6': return 6;
2384 case '7': return 7;
2385 case '8': return 8;
2386 case '9': return 9;
2387 }
2388 break;
2389 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002390 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002391 return -1;
2392 switch (Name[2]) {
2393 default: return -1;
2394 case '0': return 10;
2395 case '1': return 11;
2396 case '2': return 12;
2397 case '3': return 13;
2398 case '4': return 14;
2399 case '5': return 15;
2400 }
2401 break;
2402 }
2403
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002404 return -1;
2405}
2406
Jim Grosbach89df9962011-08-26 21:43:41 +00002407/// parseITCondCode - Try to parse a condition code for an IT instruction.
2408ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2409parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2410 SMLoc S = Parser.getTok().getLoc();
2411 const AsmToken &Tok = Parser.getTok();
2412 if (!Tok.is(AsmToken::Identifier))
2413 return MatchOperand_NoMatch;
2414 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2415 .Case("eq", ARMCC::EQ)
2416 .Case("ne", ARMCC::NE)
2417 .Case("hs", ARMCC::HS)
2418 .Case("cs", ARMCC::HS)
2419 .Case("lo", ARMCC::LO)
2420 .Case("cc", ARMCC::LO)
2421 .Case("mi", ARMCC::MI)
2422 .Case("pl", ARMCC::PL)
2423 .Case("vs", ARMCC::VS)
2424 .Case("vc", ARMCC::VC)
2425 .Case("hi", ARMCC::HI)
2426 .Case("ls", ARMCC::LS)
2427 .Case("ge", ARMCC::GE)
2428 .Case("lt", ARMCC::LT)
2429 .Case("gt", ARMCC::GT)
2430 .Case("le", ARMCC::LE)
2431 .Case("al", ARMCC::AL)
2432 .Default(~0U);
2433 if (CC == ~0U)
2434 return MatchOperand_NoMatch;
2435 Parser.Lex(); // Eat the token.
2436
2437 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2438
2439 return MatchOperand_Success;
2440}
2441
Jim Grosbach43904292011-07-25 20:14:50 +00002442/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002443/// token must be an Identifier when called, and if it is a coprocessor
2444/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002445ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002446parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002447 SMLoc S = Parser.getTok().getLoc();
2448 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002449 if (Tok.isNot(AsmToken::Identifier))
2450 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002451
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002452 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002453 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002454 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002455
2456 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002457 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002458 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002459}
2460
Jim Grosbach43904292011-07-25 20:14:50 +00002461/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002462/// token must be an Identifier when called, and if it is a coprocessor
2463/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002464ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002465parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002466 SMLoc S = Parser.getTok().getLoc();
2467 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002468 if (Tok.isNot(AsmToken::Identifier))
2469 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002470
2471 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2472 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002473 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002474
2475 Parser.Lex(); // Eat identifier token.
2476 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002477 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002478}
2479
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002480/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2481/// coproc_option : '{' imm0_255 '}'
2482ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2483parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2484 SMLoc S = Parser.getTok().getLoc();
2485
2486 // If this isn't a '{', this isn't a coprocessor immediate operand.
2487 if (Parser.getTok().isNot(AsmToken::LCurly))
2488 return MatchOperand_NoMatch;
2489 Parser.Lex(); // Eat the '{'
2490
2491 const MCExpr *Expr;
2492 SMLoc Loc = Parser.getTok().getLoc();
2493 if (getParser().ParseExpression(Expr)) {
2494 Error(Loc, "illegal expression");
2495 return MatchOperand_ParseFail;
2496 }
2497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2498 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2499 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2500 return MatchOperand_ParseFail;
2501 }
2502 int Val = CE->getValue();
2503
2504 // Check for and consume the closing '}'
2505 if (Parser.getTok().isNot(AsmToken::RCurly))
2506 return MatchOperand_ParseFail;
2507 SMLoc E = Parser.getTok().getLoc();
2508 Parser.Lex(); // Eat the '}'
2509
2510 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2511 return MatchOperand_Success;
2512}
2513
Jim Grosbachd0588e22011-09-14 18:08:35 +00002514// For register list parsing, we need to map from raw GPR register numbering
2515// to the enumeration values. The enumeration values aren't sorted by
2516// register number due to our using "sp", "lr" and "pc" as canonical names.
2517static unsigned getNextRegister(unsigned Reg) {
2518 // If this is a GPR, we need to do it manually, otherwise we can rely
2519 // on the sort ordering of the enumeration since the other reg-classes
2520 // are sane.
2521 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2522 return Reg + 1;
2523 switch(Reg) {
2524 default: assert(0 && "Invalid GPR number!");
2525 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2526 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2527 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2528 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2529 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2530 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2531 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2532 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2533 }
2534}
2535
Jim Grosbachce485e72011-11-11 21:27:40 +00002536// Return the low-subreg of a given Q register.
2537static unsigned getDRegFromQReg(unsigned QReg) {
2538 switch (QReg) {
2539 default: llvm_unreachable("expected a Q register!");
2540 case ARM::Q0: return ARM::D0;
2541 case ARM::Q1: return ARM::D2;
2542 case ARM::Q2: return ARM::D4;
2543 case ARM::Q3: return ARM::D6;
2544 case ARM::Q4: return ARM::D8;
2545 case ARM::Q5: return ARM::D10;
2546 case ARM::Q6: return ARM::D12;
2547 case ARM::Q7: return ARM::D14;
2548 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002549 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002550 case ARM::Q10: return ARM::D20;
2551 case ARM::Q11: return ARM::D22;
2552 case ARM::Q12: return ARM::D24;
2553 case ARM::Q13: return ARM::D26;
2554 case ARM::Q14: return ARM::D28;
2555 case ARM::Q15: return ARM::D30;
2556 }
2557}
2558
Jim Grosbachd0588e22011-09-14 18:08:35 +00002559/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002560bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002561parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002562 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002563 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002564 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002565 Parser.Lex(); // Eat '{' token.
2566 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002567
Jim Grosbachd0588e22011-09-14 18:08:35 +00002568 // Check the first register in the list to see what register class
2569 // this is a list of.
2570 int Reg = tryParseRegister();
2571 if (Reg == -1)
2572 return Error(RegLoc, "register expected");
2573
Jim Grosbachce485e72011-11-11 21:27:40 +00002574 // The reglist instructions have at most 16 registers, so reserve
2575 // space for that many.
2576 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2577
2578 // Allow Q regs and just interpret them as the two D sub-registers.
2579 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2580 Reg = getDRegFromQReg(Reg);
2581 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2582 ++Reg;
2583 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002584 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002585 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2586 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2587 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2588 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2589 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2590 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2591 else
2592 return Error(RegLoc, "invalid register in register list");
2593
Jim Grosbachce485e72011-11-11 21:27:40 +00002594 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002595 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002596
Jim Grosbachd0588e22011-09-14 18:08:35 +00002597 // This starts immediately after the first register token in the list,
2598 // so we can see either a comma or a minus (range separator) as a legal
2599 // next token.
2600 while (Parser.getTok().is(AsmToken::Comma) ||
2601 Parser.getTok().is(AsmToken::Minus)) {
2602 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002603 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002604 SMLoc EndLoc = Parser.getTok().getLoc();
2605 int EndReg = tryParseRegister();
2606 if (EndReg == -1)
2607 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002608 // Allow Q regs and just interpret them as the two D sub-registers.
2609 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2610 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002611 // If the register is the same as the start reg, there's nothing
2612 // more to do.
2613 if (Reg == EndReg)
2614 continue;
2615 // The register must be in the same register class as the first.
2616 if (!RC->contains(EndReg))
2617 return Error(EndLoc, "invalid register in register list");
2618 // Ranges must go from low to high.
2619 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2620 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002621
Jim Grosbachd0588e22011-09-14 18:08:35 +00002622 // Add all the registers in the range to the register list.
2623 while (Reg != EndReg) {
2624 Reg = getNextRegister(Reg);
2625 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2626 }
2627 continue;
2628 }
2629 Parser.Lex(); // Eat the comma.
2630 RegLoc = Parser.getTok().getLoc();
2631 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002632 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002633 Reg = tryParseRegister();
2634 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002635 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002636 // Allow Q regs and just interpret them as the two D sub-registers.
2637 bool isQReg = false;
2638 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2639 Reg = getDRegFromQReg(Reg);
2640 isQReg = true;
2641 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002642 // The register must be in the same register class as the first.
2643 if (!RC->contains(Reg))
2644 return Error(RegLoc, "invalid register in register list");
2645 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002646 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002647 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002648 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2649 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2650 ") in register list");
2651 continue;
2652 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002653 // VFP register lists must also be contiguous.
2654 // It's OK to use the enumeration values directly here rather, as the
2655 // VFP register classes have the enum sorted properly.
2656 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2657 Reg != OldReg + 1)
2658 return Error(RegLoc, "non-contiguous register range");
2659 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002660 if (isQReg)
2661 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002662 }
2663
Jim Grosbachd0588e22011-09-14 18:08:35 +00002664 SMLoc E = Parser.getTok().getLoc();
2665 if (Parser.getTok().isNot(AsmToken::RCurly))
2666 return Error(E, "'}' expected");
2667 Parser.Lex(); // Eat '}' token.
2668
Jim Grosbach27debd62011-12-13 21:48:29 +00002669 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002670 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002671
2672 // The ARM system instruction variants for LDM/STM have a '^' token here.
2673 if (Parser.getTok().is(AsmToken::Caret)) {
2674 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2675 Parser.Lex(); // Eat '^' token.
2676 }
2677
Bill Wendling50d0f582010-11-18 23:43:05 +00002678 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002679}
2680
Jim Grosbach98b05a52011-11-30 01:09:44 +00002681// Helper function to parse the lane index for vector lists.
2682ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002683parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2684 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002685 if (Parser.getTok().is(AsmToken::LBrac)) {
2686 Parser.Lex(); // Eat the '['.
2687 if (Parser.getTok().is(AsmToken::RBrac)) {
2688 // "Dn[]" is the 'all lanes' syntax.
2689 LaneKind = AllLanes;
2690 Parser.Lex(); // Eat the ']'.
2691 return MatchOperand_Success;
2692 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002693 if (Parser.getTok().is(AsmToken::Integer)) {
2694 int64_t Val = Parser.getTok().getIntVal();
2695 // Make this range check context sensitive for .8, .16, .32.
2696 if (Val < 0 && Val > 7)
2697 Error(Parser.getTok().getLoc(), "lane index out of range");
2698 Index = Val;
2699 LaneKind = IndexedLane;
2700 Parser.Lex(); // Eat the token;
2701 if (Parser.getTok().isNot(AsmToken::RBrac))
2702 Error(Parser.getTok().getLoc(), "']' expected");
2703 Parser.Lex(); // Eat the ']'.
2704 return MatchOperand_Success;
2705 }
2706 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002707 return MatchOperand_ParseFail;
2708 }
2709 LaneKind = NoLanes;
2710 return MatchOperand_Success;
2711}
2712
Jim Grosbach862019c2011-10-18 23:02:30 +00002713// parse a vector register list
2714ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2715parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002716 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002717 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002718 SMLoc S = Parser.getTok().getLoc();
2719 // As an extension (to match gas), support a plain D register or Q register
2720 // (without encosing curly braces) as a single or double entry list,
2721 // respectively.
2722 if (Parser.getTok().is(AsmToken::Identifier)) {
2723 int Reg = tryParseRegister();
2724 if (Reg == -1)
2725 return MatchOperand_NoMatch;
2726 SMLoc E = Parser.getTok().getLoc();
2727 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002728 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002729 if (Res != MatchOperand_Success)
2730 return Res;
2731 switch (LaneKind) {
2732 default:
2733 assert(0 && "unexpected lane kind!");
2734 case NoLanes:
2735 E = Parser.getTok().getLoc();
2736 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2737 break;
2738 case AllLanes:
2739 E = Parser.getTok().getLoc();
2740 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2741 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002742 case IndexedLane:
2743 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2744 LaneIndex, S,E));
2745 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002746 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002747 return MatchOperand_Success;
2748 }
2749 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2750 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002751 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002752 if (Res != MatchOperand_Success)
2753 return Res;
2754 switch (LaneKind) {
2755 default:
2756 assert(0 && "unexpected lane kind!");
2757 case NoLanes:
2758 E = Parser.getTok().getLoc();
2759 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2760 break;
2761 case AllLanes:
2762 E = Parser.getTok().getLoc();
2763 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2764 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002765 case IndexedLane:
2766 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2767 LaneIndex, S,E));
2768 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002769 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002770 return MatchOperand_Success;
2771 }
2772 Error(S, "vector register expected");
2773 return MatchOperand_ParseFail;
2774 }
2775
2776 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002777 return MatchOperand_NoMatch;
2778
Jim Grosbach862019c2011-10-18 23:02:30 +00002779 Parser.Lex(); // Eat '{' token.
2780 SMLoc RegLoc = Parser.getTok().getLoc();
2781
2782 int Reg = tryParseRegister();
2783 if (Reg == -1) {
2784 Error(RegLoc, "register expected");
2785 return MatchOperand_ParseFail;
2786 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002787 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002788 unsigned FirstReg = Reg;
2789 // The list is of D registers, but we also allow Q regs and just interpret
2790 // them as the two D sub-registers.
2791 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2792 FirstReg = Reg = getDRegFromQReg(Reg);
2793 ++Reg;
2794 ++Count;
2795 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002796 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002797 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002798
Jim Grosbache43862b2011-11-15 23:19:15 +00002799 while (Parser.getTok().is(AsmToken::Comma) ||
2800 Parser.getTok().is(AsmToken::Minus)) {
2801 if (Parser.getTok().is(AsmToken::Minus)) {
2802 Parser.Lex(); // Eat the minus.
2803 SMLoc EndLoc = Parser.getTok().getLoc();
2804 int EndReg = tryParseRegister();
2805 if (EndReg == -1) {
2806 Error(EndLoc, "register expected");
2807 return MatchOperand_ParseFail;
2808 }
2809 // Allow Q regs and just interpret them as the two D sub-registers.
2810 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2811 EndReg = getDRegFromQReg(EndReg) + 1;
2812 // If the register is the same as the start reg, there's nothing
2813 // more to do.
2814 if (Reg == EndReg)
2815 continue;
2816 // The register must be in the same register class as the first.
2817 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2818 Error(EndLoc, "invalid register in register list");
2819 return MatchOperand_ParseFail;
2820 }
2821 // Ranges must go from low to high.
2822 if (Reg > EndReg) {
2823 Error(EndLoc, "bad range in register list");
2824 return MatchOperand_ParseFail;
2825 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826 // Parse the lane specifier if present.
2827 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002828 unsigned NextLaneIndex;
2829 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002830 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002831 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002832 Error(EndLoc, "mismatched lane index in register list");
2833 return MatchOperand_ParseFail;
2834 }
2835 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002836
2837 // Add all the registers in the range to the register list.
2838 Count += EndReg - Reg;
2839 Reg = EndReg;
2840 continue;
2841 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002842 Parser.Lex(); // Eat the comma.
2843 RegLoc = Parser.getTok().getLoc();
2844 int OldReg = Reg;
2845 Reg = tryParseRegister();
2846 if (Reg == -1) {
2847 Error(RegLoc, "register expected");
2848 return MatchOperand_ParseFail;
2849 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002850 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002851 // It's OK to use the enumeration values directly here rather, as the
2852 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002853 //
2854 // The list is of D registers, but we also allow Q regs and just interpret
2855 // them as the two D sub-registers.
2856 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2857 Reg = getDRegFromQReg(Reg);
2858 if (Reg != OldReg + 1) {
2859 Error(RegLoc, "non-contiguous register range");
2860 return MatchOperand_ParseFail;
2861 }
2862 ++Reg;
2863 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002864 // Parse the lane specifier if present.
2865 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002866 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002867 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002868 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002869 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002870 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002871 Error(EndLoc, "mismatched lane index in register list");
2872 return MatchOperand_ParseFail;
2873 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002874 continue;
2875 }
2876 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002877 if (Reg != OldReg + 1) {
2878 Error(RegLoc, "non-contiguous register range");
2879 return MatchOperand_ParseFail;
2880 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002881 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002882 // Parse the lane specifier if present.
2883 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002884 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002886 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002887 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002888 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 Error(EndLoc, "mismatched lane index in register list");
2890 return MatchOperand_ParseFail;
2891 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002892 }
2893
2894 SMLoc E = Parser.getTok().getLoc();
2895 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2896 Error(E, "'}' expected");
2897 return MatchOperand_ParseFail;
2898 }
2899 Parser.Lex(); // Eat '}' token.
2900
Jim Grosbach98b05a52011-11-30 01:09:44 +00002901 switch (LaneKind) {
2902 default:
2903 assert(0 && "unexpected lane kind in register list.");
2904 case NoLanes:
2905 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2906 break;
2907 case AllLanes:
2908 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2909 S, E));
2910 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002911 case IndexedLane:
2912 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2913 LaneIndex, S, E));
2914 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002915 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002916 return MatchOperand_Success;
2917}
2918
Jim Grosbach43904292011-07-25 20:14:50 +00002919/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002920ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002921parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002922 SMLoc S = Parser.getTok().getLoc();
2923 const AsmToken &Tok = Parser.getTok();
2924 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2925 StringRef OptStr = Tok.getString();
2926
2927 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2928 .Case("sy", ARM_MB::SY)
2929 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002930 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002931 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002932 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002933 .Case("ishst", ARM_MB::ISHST)
2934 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002935 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002936 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002937 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002938 .Case("osh", ARM_MB::OSH)
2939 .Case("oshst", ARM_MB::OSHST)
2940 .Default(~0U);
2941
2942 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002943 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002944
2945 Parser.Lex(); // Eat identifier token.
2946 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002947 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002948}
2949
Jim Grosbach43904292011-07-25 20:14:50 +00002950/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002951ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002952parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002953 SMLoc S = Parser.getTok().getLoc();
2954 const AsmToken &Tok = Parser.getTok();
2955 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2956 StringRef IFlagsStr = Tok.getString();
2957
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002958 // An iflags string of "none" is interpreted to mean that none of the AIF
2959 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002960 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002961 if (IFlagsStr != "none") {
2962 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2963 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2964 .Case("a", ARM_PROC::A)
2965 .Case("i", ARM_PROC::I)
2966 .Case("f", ARM_PROC::F)
2967 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002968
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002969 // If some specific iflag is already set, it means that some letter is
2970 // present more than once, this is not acceptable.
2971 if (Flag == ~0U || (IFlags & Flag))
2972 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002973
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002974 IFlags |= Flag;
2975 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002976 }
2977
2978 Parser.Lex(); // Eat identifier token.
2979 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2980 return MatchOperand_Success;
2981}
2982
Jim Grosbach43904292011-07-25 20:14:50 +00002983/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002984ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002985parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002986 SMLoc S = Parser.getTok().getLoc();
2987 const AsmToken &Tok = Parser.getTok();
2988 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2989 StringRef Mask = Tok.getString();
2990
James Molloyacad68d2011-09-28 14:21:38 +00002991 if (isMClass()) {
2992 // See ARMv6-M 10.1.1
2993 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2994 .Case("apsr", 0)
2995 .Case("iapsr", 1)
2996 .Case("eapsr", 2)
2997 .Case("xpsr", 3)
2998 .Case("ipsr", 5)
2999 .Case("epsr", 6)
3000 .Case("iepsr", 7)
3001 .Case("msp", 8)
3002 .Case("psp", 9)
3003 .Case("primask", 16)
3004 .Case("basepri", 17)
3005 .Case("basepri_max", 18)
3006 .Case("faultmask", 19)
3007 .Case("control", 20)
3008 .Default(~0U);
3009
3010 if (FlagsVal == ~0U)
3011 return MatchOperand_NoMatch;
3012
3013 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3014 // basepri, basepri_max and faultmask only valid for V7m.
3015 return MatchOperand_NoMatch;
3016
3017 Parser.Lex(); // Eat identifier token.
3018 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3019 return MatchOperand_Success;
3020 }
3021
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003022 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3023 size_t Start = 0, Next = Mask.find('_');
3024 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003025 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003026 if (Next != StringRef::npos)
3027 Flags = Mask.slice(Next+1, Mask.size());
3028
3029 // FlagsVal contains the complete mask:
3030 // 3-0: Mask
3031 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3032 unsigned FlagsVal = 0;
3033
3034 if (SpecReg == "apsr") {
3035 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003036 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003037 .Case("g", 0x4) // same as CPSR_s
3038 .Case("nzcvqg", 0xc) // same as CPSR_fs
3039 .Default(~0U);
3040
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003041 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003042 if (!Flags.empty())
3043 return MatchOperand_NoMatch;
3044 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003045 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003046 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003047 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003048 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3049 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003050 for (int i = 0, e = Flags.size(); i != e; ++i) {
3051 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3052 .Case("c", 1)
3053 .Case("x", 2)
3054 .Case("s", 4)
3055 .Case("f", 8)
3056 .Default(~0U);
3057
3058 // If some specific flag is already set, it means that some letter is
3059 // present more than once, this is not acceptable.
3060 if (FlagsVal == ~0U || (FlagsVal & Flag))
3061 return MatchOperand_NoMatch;
3062 FlagsVal |= Flag;
3063 }
3064 } else // No match for special register.
3065 return MatchOperand_NoMatch;
3066
Owen Anderson7784f1d2011-10-21 18:43:28 +00003067 // Special register without flags is NOT equivalent to "fc" flags.
3068 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3069 // two lines would enable gas compatibility at the expense of breaking
3070 // round-tripping.
3071 //
3072 // if (!FlagsVal)
3073 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003074
3075 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3076 if (SpecReg == "spsr")
3077 FlagsVal |= 16;
3078
3079 Parser.Lex(); // Eat identifier token.
3080 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3081 return MatchOperand_Success;
3082}
3083
Jim Grosbachf6c05252011-07-21 17:23:04 +00003084ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3085parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3086 int Low, int High) {
3087 const AsmToken &Tok = Parser.getTok();
3088 if (Tok.isNot(AsmToken::Identifier)) {
3089 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3090 return MatchOperand_ParseFail;
3091 }
3092 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003093 std::string LowerOp = Op.lower();
3094 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003095 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3096 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3097 return MatchOperand_ParseFail;
3098 }
3099 Parser.Lex(); // Eat shift type token.
3100
3101 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003102 if (Parser.getTok().isNot(AsmToken::Hash) &&
3103 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003104 Error(Parser.getTok().getLoc(), "'#' expected");
3105 return MatchOperand_ParseFail;
3106 }
3107 Parser.Lex(); // Eat hash token.
3108
3109 const MCExpr *ShiftAmount;
3110 SMLoc Loc = Parser.getTok().getLoc();
3111 if (getParser().ParseExpression(ShiftAmount)) {
3112 Error(Loc, "illegal expression");
3113 return MatchOperand_ParseFail;
3114 }
3115 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3116 if (!CE) {
3117 Error(Loc, "constant expression expected");
3118 return MatchOperand_ParseFail;
3119 }
3120 int Val = CE->getValue();
3121 if (Val < Low || Val > High) {
3122 Error(Loc, "immediate value out of range");
3123 return MatchOperand_ParseFail;
3124 }
3125
3126 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3127
3128 return MatchOperand_Success;
3129}
3130
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003131ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3132parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3133 const AsmToken &Tok = Parser.getTok();
3134 SMLoc S = Tok.getLoc();
3135 if (Tok.isNot(AsmToken::Identifier)) {
3136 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3137 return MatchOperand_ParseFail;
3138 }
3139 int Val = StringSwitch<int>(Tok.getString())
3140 .Case("be", 1)
3141 .Case("le", 0)
3142 .Default(-1);
3143 Parser.Lex(); // Eat the token.
3144
3145 if (Val == -1) {
3146 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3147 return MatchOperand_ParseFail;
3148 }
3149 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3150 getContext()),
3151 S, Parser.getTok().getLoc()));
3152 return MatchOperand_Success;
3153}
3154
Jim Grosbach580f4a92011-07-25 22:20:28 +00003155/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3156/// instructions. Legal values are:
3157/// lsl #n 'n' in [0,31]
3158/// asr #n 'n' in [1,32]
3159/// n == 32 encoded as n == 0.
3160ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3161parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3162 const AsmToken &Tok = Parser.getTok();
3163 SMLoc S = Tok.getLoc();
3164 if (Tok.isNot(AsmToken::Identifier)) {
3165 Error(S, "shift operator 'asr' or 'lsl' expected");
3166 return MatchOperand_ParseFail;
3167 }
3168 StringRef ShiftName = Tok.getString();
3169 bool isASR;
3170 if (ShiftName == "lsl" || ShiftName == "LSL")
3171 isASR = false;
3172 else if (ShiftName == "asr" || ShiftName == "ASR")
3173 isASR = true;
3174 else {
3175 Error(S, "shift operator 'asr' or 'lsl' expected");
3176 return MatchOperand_ParseFail;
3177 }
3178 Parser.Lex(); // Eat the operator.
3179
3180 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003181 if (Parser.getTok().isNot(AsmToken::Hash) &&
3182 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003183 Error(Parser.getTok().getLoc(), "'#' expected");
3184 return MatchOperand_ParseFail;
3185 }
3186 Parser.Lex(); // Eat hash token.
3187
3188 const MCExpr *ShiftAmount;
3189 SMLoc E = Parser.getTok().getLoc();
3190 if (getParser().ParseExpression(ShiftAmount)) {
3191 Error(E, "malformed shift expression");
3192 return MatchOperand_ParseFail;
3193 }
3194 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3195 if (!CE) {
3196 Error(E, "shift amount must be an immediate");
3197 return MatchOperand_ParseFail;
3198 }
3199
3200 int64_t Val = CE->getValue();
3201 if (isASR) {
3202 // Shift amount must be in [1,32]
3203 if (Val < 1 || Val > 32) {
3204 Error(E, "'asr' shift amount must be in range [1,32]");
3205 return MatchOperand_ParseFail;
3206 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003207 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3208 if (isThumb() && Val == 32) {
3209 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3210 return MatchOperand_ParseFail;
3211 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003212 if (Val == 32) Val = 0;
3213 } else {
3214 // Shift amount must be in [1,32]
3215 if (Val < 0 || Val > 31) {
3216 Error(E, "'lsr' shift amount must be in range [0,31]");
3217 return MatchOperand_ParseFail;
3218 }
3219 }
3220
3221 E = Parser.getTok().getLoc();
3222 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3223
3224 return MatchOperand_Success;
3225}
3226
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003227/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3228/// of instructions. Legal values are:
3229/// ror #n 'n' in {0, 8, 16, 24}
3230ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3231parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3232 const AsmToken &Tok = Parser.getTok();
3233 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003234 if (Tok.isNot(AsmToken::Identifier))
3235 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003236 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003237 if (ShiftName != "ror" && ShiftName != "ROR")
3238 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003239 Parser.Lex(); // Eat the operator.
3240
3241 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003242 if (Parser.getTok().isNot(AsmToken::Hash) &&
3243 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003244 Error(Parser.getTok().getLoc(), "'#' expected");
3245 return MatchOperand_ParseFail;
3246 }
3247 Parser.Lex(); // Eat hash token.
3248
3249 const MCExpr *ShiftAmount;
3250 SMLoc E = Parser.getTok().getLoc();
3251 if (getParser().ParseExpression(ShiftAmount)) {
3252 Error(E, "malformed rotate expression");
3253 return MatchOperand_ParseFail;
3254 }
3255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3256 if (!CE) {
3257 Error(E, "rotate amount must be an immediate");
3258 return MatchOperand_ParseFail;
3259 }
3260
3261 int64_t Val = CE->getValue();
3262 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3263 // normally, zero is represented in asm by omitting the rotate operand
3264 // entirely.
3265 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3266 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3267 return MatchOperand_ParseFail;
3268 }
3269
3270 E = Parser.getTok().getLoc();
3271 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3272
3273 return MatchOperand_Success;
3274}
3275
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003276ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3277parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3278 SMLoc S = Parser.getTok().getLoc();
3279 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003280 if (Parser.getTok().isNot(AsmToken::Hash) &&
3281 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003282 Error(Parser.getTok().getLoc(), "'#' expected");
3283 return MatchOperand_ParseFail;
3284 }
3285 Parser.Lex(); // Eat hash token.
3286
3287 const MCExpr *LSBExpr;
3288 SMLoc E = Parser.getTok().getLoc();
3289 if (getParser().ParseExpression(LSBExpr)) {
3290 Error(E, "malformed immediate expression");
3291 return MatchOperand_ParseFail;
3292 }
3293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3294 if (!CE) {
3295 Error(E, "'lsb' operand must be an immediate");
3296 return MatchOperand_ParseFail;
3297 }
3298
3299 int64_t LSB = CE->getValue();
3300 // The LSB must be in the range [0,31]
3301 if (LSB < 0 || LSB > 31) {
3302 Error(E, "'lsb' operand must be in the range [0,31]");
3303 return MatchOperand_ParseFail;
3304 }
3305 E = Parser.getTok().getLoc();
3306
3307 // Expect another immediate operand.
3308 if (Parser.getTok().isNot(AsmToken::Comma)) {
3309 Error(Parser.getTok().getLoc(), "too few operands");
3310 return MatchOperand_ParseFail;
3311 }
3312 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003313 if (Parser.getTok().isNot(AsmToken::Hash) &&
3314 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003315 Error(Parser.getTok().getLoc(), "'#' expected");
3316 return MatchOperand_ParseFail;
3317 }
3318 Parser.Lex(); // Eat hash token.
3319
3320 const MCExpr *WidthExpr;
3321 if (getParser().ParseExpression(WidthExpr)) {
3322 Error(E, "malformed immediate expression");
3323 return MatchOperand_ParseFail;
3324 }
3325 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3326 if (!CE) {
3327 Error(E, "'width' operand must be an immediate");
3328 return MatchOperand_ParseFail;
3329 }
3330
3331 int64_t Width = CE->getValue();
3332 // The LSB must be in the range [1,32-lsb]
3333 if (Width < 1 || Width > 32 - LSB) {
3334 Error(E, "'width' operand must be in the range [1,32-lsb]");
3335 return MatchOperand_ParseFail;
3336 }
3337 E = Parser.getTok().getLoc();
3338
3339 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3340
3341 return MatchOperand_Success;
3342}
3343
Jim Grosbach7ce05792011-08-03 23:50:40 +00003344ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3345parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3346 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003347 // postidx_reg := '+' register {, shift}
3348 // | '-' register {, shift}
3349 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003350
3351 // This method must return MatchOperand_NoMatch without consuming any tokens
3352 // in the case where there is no match, as other alternatives take other
3353 // parse methods.
3354 AsmToken Tok = Parser.getTok();
3355 SMLoc S = Tok.getLoc();
3356 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003357 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003358 int Reg = -1;
3359 if (Tok.is(AsmToken::Plus)) {
3360 Parser.Lex(); // Eat the '+' token.
3361 haveEaten = true;
3362 } else if (Tok.is(AsmToken::Minus)) {
3363 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003364 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003365 haveEaten = true;
3366 }
3367 if (Parser.getTok().is(AsmToken::Identifier))
3368 Reg = tryParseRegister();
3369 if (Reg == -1) {
3370 if (!haveEaten)
3371 return MatchOperand_NoMatch;
3372 Error(Parser.getTok().getLoc(), "register expected");
3373 return MatchOperand_ParseFail;
3374 }
3375 SMLoc E = Parser.getTok().getLoc();
3376
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003377 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3378 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003379 if (Parser.getTok().is(AsmToken::Comma)) {
3380 Parser.Lex(); // Eat the ','.
3381 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3382 return MatchOperand_ParseFail;
3383 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003384
3385 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3386 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003387
3388 return MatchOperand_Success;
3389}
3390
Jim Grosbach251bf252011-08-10 21:56:18 +00003391ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3392parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3393 // Check for a post-index addressing register operand. Specifically:
3394 // am3offset := '+' register
3395 // | '-' register
3396 // | register
3397 // | # imm
3398 // | # + imm
3399 // | # - imm
3400
3401 // This method must return MatchOperand_NoMatch without consuming any tokens
3402 // in the case where there is no match, as other alternatives take other
3403 // parse methods.
3404 AsmToken Tok = Parser.getTok();
3405 SMLoc S = Tok.getLoc();
3406
3407 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003408 if (Parser.getTok().is(AsmToken::Hash) ||
3409 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003410 Parser.Lex(); // Eat the '#'.
3411 // Explicitly look for a '-', as we need to encode negative zero
3412 // differently.
3413 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3414 const MCExpr *Offset;
3415 if (getParser().ParseExpression(Offset))
3416 return MatchOperand_ParseFail;
3417 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3418 if (!CE) {
3419 Error(S, "constant expression expected");
3420 return MatchOperand_ParseFail;
3421 }
3422 SMLoc E = Tok.getLoc();
3423 // Negative zero is encoded as the flag value INT32_MIN.
3424 int32_t Val = CE->getValue();
3425 if (isNegative && Val == 0)
3426 Val = INT32_MIN;
3427
3428 Operands.push_back(
3429 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3430
3431 return MatchOperand_Success;
3432 }
3433
3434
3435 bool haveEaten = false;
3436 bool isAdd = true;
3437 int Reg = -1;
3438 if (Tok.is(AsmToken::Plus)) {
3439 Parser.Lex(); // Eat the '+' token.
3440 haveEaten = true;
3441 } else if (Tok.is(AsmToken::Minus)) {
3442 Parser.Lex(); // Eat the '-' token.
3443 isAdd = false;
3444 haveEaten = true;
3445 }
3446 if (Parser.getTok().is(AsmToken::Identifier))
3447 Reg = tryParseRegister();
3448 if (Reg == -1) {
3449 if (!haveEaten)
3450 return MatchOperand_NoMatch;
3451 Error(Parser.getTok().getLoc(), "register expected");
3452 return MatchOperand_ParseFail;
3453 }
3454 SMLoc E = Parser.getTok().getLoc();
3455
3456 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3457 0, S, E));
3458
3459 return MatchOperand_Success;
3460}
3461
Jim Grosbacha77295d2011-09-08 22:07:06 +00003462/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3463/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3464/// when they refer multiple MIOperands inside a single one.
3465bool ARMAsmParser::
3466cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3467 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3468 // Rt, Rt2
3469 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3470 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3471 // Create a writeback register dummy placeholder.
3472 Inst.addOperand(MCOperand::CreateReg(0));
3473 // addr
3474 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3475 // pred
3476 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3477 return true;
3478}
3479
3480/// cvtT2StrdPre - Convert parsed operands to MCInst.
3481/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3482/// when they refer multiple MIOperands inside a single one.
3483bool ARMAsmParser::
3484cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3485 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3486 // Create a writeback register dummy placeholder.
3487 Inst.addOperand(MCOperand::CreateReg(0));
3488 // Rt, Rt2
3489 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3490 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3491 // addr
3492 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3493 // pred
3494 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3495 return true;
3496}
3497
Jim Grosbacheeec0252011-09-08 00:39:19 +00003498/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3499/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3500/// when they refer multiple MIOperands inside a single one.
3501bool ARMAsmParser::
3502cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3503 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3504 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3505
3506 // Create a writeback register dummy placeholder.
3507 Inst.addOperand(MCOperand::CreateImm(0));
3508
3509 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3510 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3511 return true;
3512}
3513
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003514/// cvtStWriteBackRegT2AddrModeImm8 - 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::
3518cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3519 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3520 // Create a writeback register dummy placeholder.
3521 Inst.addOperand(MCOperand::CreateImm(0));
3522 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3523 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3524 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3525 return true;
3526}
3527
Jim Grosbach1355cf12011-07-26 17:10:22 +00003528/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003529/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3530/// when they refer multiple MIOperands inside a single one.
3531bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003532cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003533 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3534 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3535
3536 // Create a writeback register dummy placeholder.
3537 Inst.addOperand(MCOperand::CreateImm(0));
3538
Jim Grosbach7ce05792011-08-03 23:50:40 +00003539 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003540 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3541 return true;
3542}
3543
Owen Anderson9ab0f252011-08-26 20:43:14 +00003544/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3545/// 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::
3548cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3549 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
3555 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3556 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3557 return true;
3558}
3559
3560
Jim Grosbach548340c2011-08-11 19:22:40 +00003561/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3562/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3563/// when they refer multiple MIOperands inside a single one.
3564bool ARMAsmParser::
3565cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3566 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3567 // Create a writeback register dummy placeholder.
3568 Inst.addOperand(MCOperand::CreateImm(0));
3569 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3570 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3571 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3572 return true;
3573}
3574
Jim Grosbach1355cf12011-07-26 17:10:22 +00003575/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003576/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3577/// when they refer multiple MIOperands inside a single one.
3578bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003579cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003580 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3581 // Create a writeback register dummy placeholder.
3582 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003583 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3584 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3585 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003586 return true;
3587}
3588
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003589/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3590/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3591/// when they refer multiple MIOperands inside a single one.
3592bool ARMAsmParser::
3593cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3594 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3595 // Create a writeback register dummy placeholder.
3596 Inst.addOperand(MCOperand::CreateImm(0));
3597 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3598 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3599 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3600 return true;
3601}
3602
Jim Grosbach7ce05792011-08-03 23:50:40 +00003603/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3604/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3605/// when they refer multiple MIOperands inside a single one.
3606bool ARMAsmParser::
3607cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3608 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3609 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003610 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611 // Create a writeback register dummy placeholder.
3612 Inst.addOperand(MCOperand::CreateImm(0));
3613 // addr
3614 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3615 // offset
3616 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3617 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003618 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3619 return true;
3620}
3621
Jim Grosbach7ce05792011-08-03 23:50:40 +00003622/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003623/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3624/// when they refer multiple MIOperands inside a single one.
3625bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003626cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3627 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3628 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003629 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003630 // Create a writeback register dummy placeholder.
3631 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003632 // addr
3633 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3634 // offset
3635 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3636 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003637 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3638 return true;
3639}
3640
Jim Grosbach7ce05792011-08-03 23:50:40 +00003641/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003642/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3643/// when they refer multiple MIOperands inside a single one.
3644bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003645cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3646 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003647 // Create a writeback register dummy placeholder.
3648 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003649 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003650 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003651 // addr
3652 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3653 // offset
3654 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3655 // pred
3656 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3657 return true;
3658}
3659
3660/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3661/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3662/// when they refer multiple MIOperands inside a single one.
3663bool ARMAsmParser::
3664cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3665 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3666 // Create a writeback register dummy placeholder.
3667 Inst.addOperand(MCOperand::CreateImm(0));
3668 // Rt
3669 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3670 // addr
3671 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3672 // offset
3673 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3674 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003675 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3676 return true;
3677}
3678
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003679/// cvtLdrdPre - Convert parsed operands to MCInst.
3680/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3681/// when they refer multiple MIOperands inside a single one.
3682bool ARMAsmParser::
3683cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3684 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3685 // Rt, Rt2
3686 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3687 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3688 // Create a writeback register dummy placeholder.
3689 Inst.addOperand(MCOperand::CreateImm(0));
3690 // addr
3691 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3692 // pred
3693 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3694 return true;
3695}
3696
Jim Grosbach14605d12011-08-11 20:28:23 +00003697/// cvtStrdPre - Convert parsed operands to MCInst.
3698/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3699/// when they refer multiple MIOperands inside a single one.
3700bool ARMAsmParser::
3701cvtStrdPre(MCInst &Inst, unsigned Opcode,
3702 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3703 // Create a writeback register dummy placeholder.
3704 Inst.addOperand(MCOperand::CreateImm(0));
3705 // Rt, Rt2
3706 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3707 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3708 // addr
3709 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3710 // pred
3711 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3712 return true;
3713}
3714
Jim Grosbach623a4542011-08-10 22:42:16 +00003715/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3716/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3717/// when they refer multiple MIOperands inside a single one.
3718bool ARMAsmParser::
3719cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3720 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3721 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3722 // Create a writeback register dummy placeholder.
3723 Inst.addOperand(MCOperand::CreateImm(0));
3724 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3725 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3726 return true;
3727}
3728
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003729/// cvtThumbMultiple- Convert parsed operands to MCInst.
3730/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3731/// when they refer multiple MIOperands inside a single one.
3732bool ARMAsmParser::
3733cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3734 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3735 // The second source operand must be the same register as the destination
3736 // operand.
3737 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003738 (((ARMOperand*)Operands[3])->getReg() !=
3739 ((ARMOperand*)Operands[5])->getReg()) &&
3740 (((ARMOperand*)Operands[3])->getReg() !=
3741 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003742 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003743 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003744 return false;
3745 }
3746 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3747 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003748 // If we have a three-operand form, make sure to set Rn to be the operand
3749 // that isn't the same as Rd.
3750 unsigned RegOp = 4;
3751 if (Operands.size() == 6 &&
3752 ((ARMOperand*)Operands[4])->getReg() ==
3753 ((ARMOperand*)Operands[3])->getReg())
3754 RegOp = 5;
3755 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3756 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003757 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3758
3759 return true;
3760}
Jim Grosbach623a4542011-08-10 22:42:16 +00003761
Jim Grosbach12431322011-10-24 22:16:58 +00003762bool ARMAsmParser::
3763cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3764 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3765 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003766 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003767 // Create a writeback register dummy placeholder.
3768 Inst.addOperand(MCOperand::CreateImm(0));
3769 // Vn
3770 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3771 // pred
3772 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3773 return true;
3774}
3775
3776bool ARMAsmParser::
3777cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3778 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3779 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003780 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003781 // Create a writeback register dummy placeholder.
3782 Inst.addOperand(MCOperand::CreateImm(0));
3783 // Vn
3784 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3785 // Vm
3786 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3787 // pred
3788 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3789 return true;
3790}
3791
Jim Grosbach4334e032011-10-31 21:50:31 +00003792bool ARMAsmParser::
3793cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3794 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3795 // Create a writeback register dummy placeholder.
3796 Inst.addOperand(MCOperand::CreateImm(0));
3797 // Vn
3798 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3799 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003800 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003801 // pred
3802 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3803 return true;
3804}
3805
3806bool ARMAsmParser::
3807cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3808 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3809 // Create a writeback register dummy placeholder.
3810 Inst.addOperand(MCOperand::CreateImm(0));
3811 // Vn
3812 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3813 // Vm
3814 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
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
Bill Wendlinge7176102010-11-06 22:36:58 +00003822/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003823/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003824bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003825parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003826 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003827 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003828 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003829 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003830 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003831
Sean Callanan18b83232010-01-19 21:44:56 +00003832 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003833 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003834 if (BaseRegNum == -1)
3835 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003836
Daniel Dunbar05710932011-01-18 05:34:17 +00003837 // The next token must either be a comma or a closing bracket.
3838 const AsmToken &Tok = Parser.getTok();
3839 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003840 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003841
Jim Grosbach7ce05792011-08-03 23:50:40 +00003842 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003843 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003844 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003845
Jim Grosbach7ce05792011-08-03 23:50:40 +00003846 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003847 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003848
Jim Grosbachfb12f352011-09-19 18:42:21 +00003849 // If there's a pre-indexing writeback marker, '!', just add it as a token
3850 // operand. It's rather odd, but syntactically valid.
3851 if (Parser.getTok().is(AsmToken::Exclaim)) {
3852 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3853 Parser.Lex(); // Eat the '!'.
3854 }
3855
Jim Grosbach7ce05792011-08-03 23:50:40 +00003856 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003857 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003858
Jim Grosbach7ce05792011-08-03 23:50:40 +00003859 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3860 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003861
Jim Grosbach57dcb852011-10-11 17:29:55 +00003862 // If we have a ':', it's an alignment specifier.
3863 if (Parser.getTok().is(AsmToken::Colon)) {
3864 Parser.Lex(); // Eat the ':'.
3865 E = Parser.getTok().getLoc();
3866
3867 const MCExpr *Expr;
3868 if (getParser().ParseExpression(Expr))
3869 return true;
3870
3871 // The expression has to be a constant. Memory references with relocations
3872 // don't come through here, as they use the <label> forms of the relevant
3873 // instructions.
3874 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3875 if (!CE)
3876 return Error (E, "constant expression expected");
3877
3878 unsigned Align = 0;
3879 switch (CE->getValue()) {
3880 default:
3881 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3882 case 64: Align = 8; break;
3883 case 128: Align = 16; break;
3884 case 256: Align = 32; break;
3885 }
3886
3887 // Now we should have the closing ']'
3888 E = Parser.getTok().getLoc();
3889 if (Parser.getTok().isNot(AsmToken::RBrac))
3890 return Error(E, "']' expected");
3891 Parser.Lex(); // Eat right bracket token.
3892
3893 // Don't worry about range checking the value here. That's handled by
3894 // the is*() predicates.
3895 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3896 ARM_AM::no_shift, 0, Align,
3897 false, S, E));
3898
3899 // If there's a pre-indexing writeback marker, '!', just add it as a token
3900 // operand.
3901 if (Parser.getTok().is(AsmToken::Exclaim)) {
3902 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3903 Parser.Lex(); // Eat the '!'.
3904 }
3905
3906 return false;
3907 }
3908
3909 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003910 // offset. Be friendly and also accept a plain integer (without a leading
3911 // hash) for gas compatibility.
3912 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003913 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003914 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003915 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003916 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003917 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003918
Owen Anderson0da10cf2011-08-29 19:36:44 +00003919 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003920 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003921 if (getParser().ParseExpression(Offset))
3922 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003923
3924 // The expression has to be a constant. Memory references with relocations
3925 // don't come through here, as they use the <label> forms of the relevant
3926 // instructions.
3927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3928 if (!CE)
3929 return Error (E, "constant expression expected");
3930
Owen Anderson0da10cf2011-08-29 19:36:44 +00003931 // If the constant was #-0, represent it as INT32_MIN.
3932 int32_t Val = CE->getValue();
3933 if (isNegative && Val == 0)
3934 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3935
Jim Grosbach7ce05792011-08-03 23:50:40 +00003936 // Now we should have the closing ']'
3937 E = Parser.getTok().getLoc();
3938 if (Parser.getTok().isNot(AsmToken::RBrac))
3939 return Error(E, "']' expected");
3940 Parser.Lex(); // Eat right bracket token.
3941
3942 // Don't worry about range checking the value here. That's handled by
3943 // the is*() predicates.
3944 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003945 ARM_AM::no_shift, 0, 0,
3946 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003947
3948 // If there's a pre-indexing writeback marker, '!', just add it as a token
3949 // operand.
3950 if (Parser.getTok().is(AsmToken::Exclaim)) {
3951 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3952 Parser.Lex(); // Eat the '!'.
3953 }
3954
3955 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003956 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003957
3958 // The register offset is optionally preceded by a '+' or '-'
3959 bool isNegative = false;
3960 if (Parser.getTok().is(AsmToken::Minus)) {
3961 isNegative = true;
3962 Parser.Lex(); // Eat the '-'.
3963 } else if (Parser.getTok().is(AsmToken::Plus)) {
3964 // Nothing to do.
3965 Parser.Lex(); // Eat the '+'.
3966 }
3967
3968 E = Parser.getTok().getLoc();
3969 int OffsetRegNum = tryParseRegister();
3970 if (OffsetRegNum == -1)
3971 return Error(E, "register expected");
3972
3973 // If there's a shift operator, handle it.
3974 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003975 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003976 if (Parser.getTok().is(AsmToken::Comma)) {
3977 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003978 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003979 return true;
3980 }
3981
3982 // Now we should have the closing ']'
3983 E = Parser.getTok().getLoc();
3984 if (Parser.getTok().isNot(AsmToken::RBrac))
3985 return Error(E, "']' expected");
3986 Parser.Lex(); // Eat right bracket token.
3987
3988 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003989 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003990 S, E));
3991
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003992 // If there's a pre-indexing writeback marker, '!', just add it as a token
3993 // operand.
3994 if (Parser.getTok().is(AsmToken::Exclaim)) {
3995 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3996 Parser.Lex(); // Eat the '!'.
3997 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003998
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003999 return false;
4000}
4001
Jim Grosbach7ce05792011-08-03 23:50:40 +00004002/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004003/// ( lsl | lsr | asr | ror ) , # shift_amount
4004/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004005/// return true if it parses a shift otherwise it returns false.
4006bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4007 unsigned &Amount) {
4008 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004009 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004010 if (Tok.isNot(AsmToken::Identifier))
4011 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004012 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004013 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4014 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004015 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004016 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004017 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004018 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004019 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004020 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004021 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004022 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004023 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004024 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004025 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004026 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004027
Jim Grosbach7ce05792011-08-03 23:50:40 +00004028 // rrx stands alone.
4029 Amount = 0;
4030 if (St != ARM_AM::rrx) {
4031 Loc = Parser.getTok().getLoc();
4032 // A '#' and a shift amount.
4033 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004034 if (HashTok.isNot(AsmToken::Hash) &&
4035 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004036 return Error(HashTok.getLoc(), "'#' expected");
4037 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004038
Jim Grosbach7ce05792011-08-03 23:50:40 +00004039 const MCExpr *Expr;
4040 if (getParser().ParseExpression(Expr))
4041 return true;
4042 // Range check the immediate.
4043 // lsl, ror: 0 <= imm <= 31
4044 // lsr, asr: 0 <= imm <= 32
4045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4046 if (!CE)
4047 return Error(Loc, "shift amount must be an immediate");
4048 int64_t Imm = CE->getValue();
4049 if (Imm < 0 ||
4050 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4051 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4052 return Error(Loc, "immediate shift value out of range");
4053 Amount = Imm;
4054 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004055
4056 return false;
4057}
4058
Jim Grosbach9d390362011-10-03 23:38:36 +00004059/// parseFPImm - A floating point immediate expression operand.
4060ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4061parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4062 SMLoc S = Parser.getTok().getLoc();
4063
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004064 if (Parser.getTok().isNot(AsmToken::Hash) &&
4065 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004066 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004067
4068 // Disambiguate the VMOV forms that can accept an FP immediate.
4069 // vmov.f32 <sreg>, #imm
4070 // vmov.f64 <dreg>, #imm
4071 // vmov.f32 <dreg>, #imm @ vector f32x2
4072 // vmov.f32 <qreg>, #imm @ vector f32x4
4073 //
4074 // There are also the NEON VMOV instructions which expect an
4075 // integer constant. Make sure we don't try to parse an FPImm
4076 // for these:
4077 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4078 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4079 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4080 TyOp->getToken() != ".f64"))
4081 return MatchOperand_NoMatch;
4082
Jim Grosbach9d390362011-10-03 23:38:36 +00004083 Parser.Lex(); // Eat the '#'.
4084
4085 // Handle negation, as that still comes through as a separate token.
4086 bool isNegative = false;
4087 if (Parser.getTok().is(AsmToken::Minus)) {
4088 isNegative = true;
4089 Parser.Lex();
4090 }
4091 const AsmToken &Tok = Parser.getTok();
4092 if (Tok.is(AsmToken::Real)) {
4093 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4094 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4095 // If we had a '-' in front, toggle the sign bit.
4096 IntVal ^= (uint64_t)isNegative << 63;
4097 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4098 Parser.Lex(); // Eat the token.
4099 if (Val == -1) {
4100 TokError("floating point value out of range");
4101 return MatchOperand_ParseFail;
4102 }
4103 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4104 return MatchOperand_Success;
4105 }
4106 if (Tok.is(AsmToken::Integer)) {
4107 int64_t Val = Tok.getIntVal();
4108 Parser.Lex(); // Eat the token.
4109 if (Val > 255 || Val < 0) {
4110 TokError("encoded floating point value out of range");
4111 return MatchOperand_ParseFail;
4112 }
4113 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4114 return MatchOperand_Success;
4115 }
4116
4117 TokError("invalid floating point immediate");
4118 return MatchOperand_ParseFail;
4119}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004120/// Parse a arm instruction operand. For now this parses the operand regardless
4121/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004122bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004123 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004124 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004125
4126 // Check if the current operand has a custom associated parser, if so, try to
4127 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004128 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4129 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004130 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004131 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4132 // there was a match, but an error occurred, in which case, just return that
4133 // the operand parsing failed.
4134 if (ResTy == MatchOperand_ParseFail)
4135 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004137 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004138 default:
4139 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004140 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004141 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004142 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004143 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004144 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004145 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004146 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004147 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004148 else if (Res == -1) // irrecoverable error
4149 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004150 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4151 S = Parser.getTok().getLoc();
4152 Parser.Lex();
4153 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4154 return false;
4155 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004156
4157 // Fall though for the Identifier case that is not a register or a
4158 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004159 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004160 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004161 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004162 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004163 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004164 // This was not a register so parse other operands that start with an
4165 // identifier (like labels) as expressions and create them as immediates.
4166 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004167 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004168 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004169 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004170 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004171 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4172 return false;
4173 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004174 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004175 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004176 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004177 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004178 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004179 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004180 // #42 -> immediate.
4181 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004182 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004183 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004184 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004185 const MCExpr *ImmVal;
4186 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004187 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004189 if (CE) {
4190 int32_t Val = CE->getValue();
4191 if (isNegative && Val == 0)
4192 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004193 }
Sean Callanan76264762010-04-02 22:27:05 +00004194 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004195 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4196 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004197 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004198 case AsmToken::Colon: {
4199 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004200 // FIXME: Check it's an expression prefix,
4201 // e.g. (FOO - :lower16:BAR) isn't legal.
4202 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004203 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004204 return true;
4205
Evan Cheng75972122011-01-13 07:58:56 +00004206 const MCExpr *SubExprVal;
4207 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004208 return true;
4209
Evan Cheng75972122011-01-13 07:58:56 +00004210 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4211 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004212 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004213 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004214 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004215 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004216 }
4217}
4218
Jim Grosbach1355cf12011-07-26 17:10:22 +00004219// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004220// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004221bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004222 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004223
4224 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004225 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004226 Parser.Lex(); // Eat ':'
4227
4228 if (getLexer().isNot(AsmToken::Identifier)) {
4229 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4230 return true;
4231 }
4232
4233 StringRef IDVal = Parser.getTok().getIdentifier();
4234 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004235 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004236 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004237 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004238 } else {
4239 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4240 return true;
4241 }
4242 Parser.Lex();
4243
4244 if (getLexer().isNot(AsmToken::Colon)) {
4245 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4246 return true;
4247 }
4248 Parser.Lex(); // Eat the last ':'
4249 return false;
4250}
4251
Daniel Dunbar352e1482011-01-11 15:59:50 +00004252/// \brief Given a mnemonic, split out possible predication code and carry
4253/// setting letters to form a canonical mnemonic and flags.
4254//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004255// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004256// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004257StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004258 unsigned &PredicationCode,
4259 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004260 unsigned &ProcessorIMod,
4261 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004262 PredicationCode = ARMCC::AL;
4263 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004264 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004265
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004266 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004267 //
4268 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004269 if ((Mnemonic == "movs" && isThumb()) ||
4270 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4271 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4272 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4273 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4274 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4275 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4276 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004277 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004278
Jim Grosbach3f00e312011-07-11 17:09:57 +00004279 // First, split out any predication code. Ignore mnemonics we know aren't
4280 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004281 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004282 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004283 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004284 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004285 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4286 .Case("eq", ARMCC::EQ)
4287 .Case("ne", ARMCC::NE)
4288 .Case("hs", ARMCC::HS)
4289 .Case("cs", ARMCC::HS)
4290 .Case("lo", ARMCC::LO)
4291 .Case("cc", ARMCC::LO)
4292 .Case("mi", ARMCC::MI)
4293 .Case("pl", ARMCC::PL)
4294 .Case("vs", ARMCC::VS)
4295 .Case("vc", ARMCC::VC)
4296 .Case("hi", ARMCC::HI)
4297 .Case("ls", ARMCC::LS)
4298 .Case("ge", ARMCC::GE)
4299 .Case("lt", ARMCC::LT)
4300 .Case("gt", ARMCC::GT)
4301 .Case("le", ARMCC::LE)
4302 .Case("al", ARMCC::AL)
4303 .Default(~0U);
4304 if (CC != ~0U) {
4305 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4306 PredicationCode = CC;
4307 }
Bill Wendling52925b62010-10-29 23:50:21 +00004308 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004309
Daniel Dunbar352e1482011-01-11 15:59:50 +00004310 // Next, determine if we have a carry setting bit. We explicitly ignore all
4311 // the instructions we know end in 's'.
4312 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004313 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004314 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4315 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4316 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004317 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004318 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbachf1015402011-12-13 20:13:48 +00004319 Mnemonic == "fsts" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004320 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004321 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4322 CarrySetting = true;
4323 }
4324
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004325 // The "cps" instruction can have a interrupt mode operand which is glued into
4326 // the mnemonic. Check if this is the case, split it and parse the imod op
4327 if (Mnemonic.startswith("cps")) {
4328 // Split out any imod code.
4329 unsigned IMod =
4330 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4331 .Case("ie", ARM_PROC::IE)
4332 .Case("id", ARM_PROC::ID)
4333 .Default(~0U);
4334 if (IMod != ~0U) {
4335 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4336 ProcessorIMod = IMod;
4337 }
4338 }
4339
Jim Grosbach89df9962011-08-26 21:43:41 +00004340 // The "it" instruction has the condition mask on the end of the mnemonic.
4341 if (Mnemonic.startswith("it")) {
4342 ITMask = Mnemonic.slice(2, Mnemonic.size());
4343 Mnemonic = Mnemonic.slice(0, 2);
4344 }
4345
Daniel Dunbar352e1482011-01-11 15:59:50 +00004346 return Mnemonic;
4347}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004348
4349/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4350/// inclusion of carry set or predication code operands.
4351//
4352// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004353void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004354getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004355 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004356 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4357 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004358 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004359 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004360 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004361 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004362 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004363 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004364 Mnemonic == "mla" || Mnemonic == "smlal" ||
4365 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004366 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004367 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004368 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004369
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004370 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4371 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4372 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4373 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004374 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4375 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004376 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004377 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4378 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4379 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004380 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4381 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004382 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004383 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004384 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004385 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004386
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004387 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004388 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004389 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004390 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004391 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004392}
4393
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004394bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4395 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004396 // FIXME: This is all horribly hacky. We really need a better way to deal
4397 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004398
4399 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4400 // another does not. Specifically, the MOVW instruction does not. So we
4401 // special case it here and remove the defaulted (non-setting) cc_out
4402 // operand if that's the instruction we're trying to match.
4403 //
4404 // We do this as post-processing of the explicit operands rather than just
4405 // conditionally adding the cc_out in the first place because we need
4406 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004407 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004408 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4409 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4410 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4411 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004412
4413 // Register-register 'add' for thumb does not have a cc_out operand
4414 // when there are only two register operands.
4415 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4416 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4417 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4418 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4419 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004420 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004421 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4422 // have to check the immediate range here since Thumb2 has a variant
4423 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004424 if (((isThumb() && Mnemonic == "add") ||
4425 (isThumbTwo() && Mnemonic == "sub")) &&
4426 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004427 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4428 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4429 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004430 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4431 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4432 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004433 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004434 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4435 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004436 // selecting via the generic "add" mnemonic, so to know that we
4437 // should remove the cc_out operand, we have to explicitly check that
4438 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004439 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4440 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004441 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4442 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4443 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4444 // Nest conditions rather than one big 'if' statement for readability.
4445 //
4446 // If either register is a high reg, it's either one of the SP
4447 // variants (handled above) or a 32-bit encoding, so we just
4448 // check against T3.
4449 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4450 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4451 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4452 return false;
4453 // If both registers are low, we're in an IT block, and the immediate is
4454 // in range, we should use encoding T1 instead, which has a cc_out.
4455 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004456 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004457 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4458 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4459 return false;
4460
4461 // Otherwise, we use encoding T4, which does not have a cc_out
4462 // operand.
4463 return true;
4464 }
4465
Jim Grosbach64944f42011-09-14 21:00:40 +00004466 // The thumb2 multiply instruction doesn't have a CCOut register, so
4467 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4468 // use the 16-bit encoding or not.
4469 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4470 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4471 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4472 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4473 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4474 // If the registers aren't low regs, the destination reg isn't the
4475 // same as one of the source regs, or the cc_out operand is zero
4476 // outside of an IT block, we have to use the 32-bit encoding, so
4477 // remove the cc_out operand.
4478 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4479 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004480 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004481 !inITBlock() ||
4482 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4483 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4484 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4485 static_cast<ARMOperand*>(Operands[4])->getReg())))
4486 return true;
4487
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004488 // Also check the 'mul' syntax variant that doesn't specify an explicit
4489 // destination register.
4490 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4491 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4492 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4493 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4494 // If the registers aren't low regs or the cc_out operand is zero
4495 // outside of an IT block, we have to use the 32-bit encoding, so
4496 // remove the cc_out operand.
4497 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4498 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4499 !inITBlock()))
4500 return true;
4501
Jim Grosbach64944f42011-09-14 21:00:40 +00004502
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004503
Jim Grosbachf69c8042011-08-24 21:42:27 +00004504 // Register-register 'add/sub' for thumb does not have a cc_out operand
4505 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4506 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4507 // right, this will result in better diagnostics (which operand is off)
4508 // anyway.
4509 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4510 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004511 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4512 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4513 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4514 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004515
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004516 return false;
4517}
4518
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004519static bool isDataTypeToken(StringRef Tok) {
4520 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4521 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4522 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4523 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4524 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4525 Tok == ".f" || Tok == ".d";
4526}
4527
4528// FIXME: This bit should probably be handled via an explicit match class
4529// in the .td files that matches the suffix instead of having it be
4530// a literal string token the way it is now.
4531static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4532 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4533}
4534
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004535static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004536/// Parse an arm instruction mnemonic followed by its operands.
4537bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4538 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004539 // Apply mnemonic aliases before doing anything else, as the destination
4540 // mnemnonic may include suffices and we want to handle them normally.
4541 // The generic tblgen'erated code does this later, at the start of
4542 // MatchInstructionImpl(), but that's too late for aliases that include
4543 // any sort of suffix.
4544 unsigned AvailableFeatures = getAvailableFeatures();
4545 applyMnemonicAliases(Name, AvailableFeatures);
4546
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004547 // Create the leading tokens for the mnemonic, split by '.' characters.
4548 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004549 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004550
Daniel Dunbar352e1482011-01-11 15:59:50 +00004551 // Split out the predication code and carry setting flag from the mnemonic.
4552 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004553 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004554 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004555 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004556 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004557 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004558
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004559 // In Thumb1, only the branch (B) instruction can be predicated.
4560 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4561 Parser.EatToEndOfStatement();
4562 return Error(NameLoc, "conditional execution not supported in Thumb1");
4563 }
4564
Jim Grosbachffa32252011-07-19 19:13:28 +00004565 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4566
Jim Grosbach89df9962011-08-26 21:43:41 +00004567 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4568 // is the mask as it will be for the IT encoding if the conditional
4569 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4570 // where the conditional bit0 is zero, the instruction post-processing
4571 // will adjust the mask accordingly.
4572 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004573 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4574 if (ITMask.size() > 3) {
4575 Parser.EatToEndOfStatement();
4576 return Error(Loc, "too many conditions on IT instruction");
4577 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004578 unsigned Mask = 8;
4579 for (unsigned i = ITMask.size(); i != 0; --i) {
4580 char pos = ITMask[i - 1];
4581 if (pos != 't' && pos != 'e') {
4582 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004583 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004584 }
4585 Mask >>= 1;
4586 if (ITMask[i - 1] == 't')
4587 Mask |= 8;
4588 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004589 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004590 }
4591
Jim Grosbachffa32252011-07-19 19:13:28 +00004592 // FIXME: This is all a pretty gross hack. We should automatically handle
4593 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004594
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004595 // Next, add the CCOut and ConditionCode operands, if needed.
4596 //
4597 // For mnemonics which can ever incorporate a carry setting bit or predication
4598 // code, our matching model involves us always generating CCOut and
4599 // ConditionCode operands to match the mnemonic "as written" and then we let
4600 // the matcher deal with finding the right instruction or generating an
4601 // appropriate error.
4602 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004603 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004604
Jim Grosbach33c16a22011-07-14 22:04:21 +00004605 // If we had a carry-set on an instruction that can't do that, issue an
4606 // error.
4607 if (!CanAcceptCarrySet && CarrySetting) {
4608 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004609 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004610 "' can not set flags, but 's' suffix specified");
4611 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004612 // If we had a predication code on an instruction that can't do that, issue an
4613 // error.
4614 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4615 Parser.EatToEndOfStatement();
4616 return Error(NameLoc, "instruction '" + Mnemonic +
4617 "' is not predicable, but condition code specified");
4618 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004619
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004620 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004621 if (CanAcceptCarrySet) {
4622 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004623 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004624 Loc));
4625 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004626
4627 // Add the predication code operand, if necessary.
4628 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004629 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4630 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004631 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004632 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004633 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004634
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004635 // Add the processor imod operand, if necessary.
4636 if (ProcessorIMod) {
4637 Operands.push_back(ARMOperand::CreateImm(
4638 MCConstantExpr::Create(ProcessorIMod, getContext()),
4639 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004640 }
4641
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004642 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004643 while (Next != StringRef::npos) {
4644 Start = Next;
4645 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004646 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004647
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004648 // Some NEON instructions have an optional datatype suffix that is
4649 // completely ignored. Check for that.
4650 if (isDataTypeToken(ExtraToken) &&
4651 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4652 continue;
4653
Jim Grosbach81d2e392011-09-07 16:06:04 +00004654 if (ExtraToken != ".n") {
4655 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4656 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4657 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004658 }
4659
4660 // Read the remaining operands.
4661 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004662 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004663 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004664 Parser.EatToEndOfStatement();
4665 return true;
4666 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004667
4668 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004669 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004670
4671 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004672 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004673 Parser.EatToEndOfStatement();
4674 return true;
4675 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004676 }
4677 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004678
Chris Lattnercbf8a982010-09-11 16:18:25 +00004679 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004680 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004681 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004682 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004683 }
Bill Wendling146018f2010-11-06 21:42:12 +00004684
Chris Lattner34e53142010-09-08 05:10:46 +00004685 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004686
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004687 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4688 // do and don't have a cc_out optional-def operand. With some spot-checks
4689 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004690 // parse and adjust accordingly before actually matching. We shouldn't ever
4691 // try to remove a cc_out operand that was explicitly set on the the
4692 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4693 // table driven matcher doesn't fit well with the ARM instruction set.
4694 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004695 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4696 Operands.erase(Operands.begin() + 1);
4697 delete Op;
4698 }
4699
Jim Grosbachcf121c32011-07-28 21:57:55 +00004700 // ARM mode 'blx' need special handling, as the register operand version
4701 // is predicable, but the label operand version is not. So, we can't rely
4702 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004703 // a k_CondCode operand in the list. If we're trying to match the label
4704 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004705 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4706 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4707 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4708 Operands.erase(Operands.begin() + 1);
4709 delete Op;
4710 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004711
4712 // The vector-compare-to-zero instructions have a literal token "#0" at
4713 // the end that comes to here as an immediate operand. Convert it to a
4714 // token to play nicely with the matcher.
4715 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4716 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4717 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4718 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4720 if (CE && CE->getValue() == 0) {
4721 Operands.erase(Operands.begin() + 5);
4722 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4723 delete Op;
4724 }
4725 }
Jim Grosbach68259142011-10-03 22:30:24 +00004726 // VCMP{E} does the same thing, but with a different operand count.
4727 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4728 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4729 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4730 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4731 if (CE && CE->getValue() == 0) {
4732 Operands.erase(Operands.begin() + 4);
4733 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4734 delete Op;
4735 }
4736 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004737 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004738 // end. Convert it to a token here. Take care not to convert those
4739 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004740 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004741 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4742 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004743 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4744 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004746 if (CE && CE->getValue() == 0 &&
4747 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004748 // The cc_out operand matches the IT block.
4749 ((inITBlock() != CarrySetting) &&
4750 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004751 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004752 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004753 Operands.erase(Operands.begin() + 5);
4754 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4755 delete Op;
4756 }
4757 }
4758
Chris Lattner98986712010-01-14 22:21:20 +00004759 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004760}
4761
Jim Grosbach189610f2011-07-26 18:25:39 +00004762// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004763
4764// return 'true' if register list contains non-low GPR registers,
4765// 'false' otherwise. If Reg is in the register list or is HiReg, set
4766// 'containsReg' to true.
4767static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4768 unsigned HiReg, bool &containsReg) {
4769 containsReg = false;
4770 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4771 unsigned OpReg = Inst.getOperand(i).getReg();
4772 if (OpReg == Reg)
4773 containsReg = true;
4774 // Anything other than a low register isn't legal here.
4775 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4776 return true;
4777 }
4778 return false;
4779}
4780
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004781// Check if the specified regisgter is in the register list of the inst,
4782// starting at the indicated operand number.
4783static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4784 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4785 unsigned OpReg = Inst.getOperand(i).getReg();
4786 if (OpReg == Reg)
4787 return true;
4788 }
4789 return false;
4790}
4791
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004792// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4793// the ARMInsts array) instead. Getting that here requires awkward
4794// API changes, though. Better way?
4795namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004796extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004797}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004798static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004799 return ARMInsts[Opcode];
4800}
4801
Jim Grosbach189610f2011-07-26 18:25:39 +00004802// FIXME: We would really like to be able to tablegen'erate this.
4803bool ARMAsmParser::
4804validateInstruction(MCInst &Inst,
4805 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004806 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004807 SMLoc Loc = Operands[0]->getStartLoc();
4808 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004809 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4810 // being allowed in IT blocks, but not being predicable. It just always
4811 // executes.
4812 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004813 unsigned bit = 1;
4814 if (ITState.FirstCond)
4815 ITState.FirstCond = false;
4816 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004817 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004818 // The instruction must be predicable.
4819 if (!MCID.isPredicable())
4820 return Error(Loc, "instructions in IT block must be predicable");
4821 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4822 unsigned ITCond = bit ? ITState.Cond :
4823 ARMCC::getOppositeCondition(ITState.Cond);
4824 if (Cond != ITCond) {
4825 // Find the condition code Operand to get its SMLoc information.
4826 SMLoc CondLoc;
4827 for (unsigned i = 1; i < Operands.size(); ++i)
4828 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4829 CondLoc = Operands[i]->getStartLoc();
4830 return Error(CondLoc, "incorrect condition in IT block; got '" +
4831 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4832 "', but expected '" +
4833 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4834 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004835 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004836 } else if (isThumbTwo() && MCID.isPredicable() &&
4837 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004838 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4839 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004840 return Error(Loc, "predicated instructions must be in IT block");
4841
Jim Grosbach189610f2011-07-26 18:25:39 +00004842 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004843 case ARM::LDRD:
4844 case ARM::LDRD_PRE:
4845 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004846 case ARM::LDREXD: {
4847 // Rt2 must be Rt + 1.
4848 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4849 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4850 if (Rt2 != Rt + 1)
4851 return Error(Operands[3]->getStartLoc(),
4852 "destination operands must be sequential");
4853 return false;
4854 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004855 case ARM::STRD: {
4856 // Rt2 must be Rt + 1.
4857 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4858 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4859 if (Rt2 != Rt + 1)
4860 return Error(Operands[3]->getStartLoc(),
4861 "source operands must be sequential");
4862 return false;
4863 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004864 case ARM::STRD_PRE:
4865 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004866 case ARM::STREXD: {
4867 // Rt2 must be Rt + 1.
4868 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4869 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4870 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004871 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004872 "source operands must be sequential");
4873 return false;
4874 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004875 case ARM::SBFX:
4876 case ARM::UBFX: {
4877 // width must be in range [1, 32-lsb]
4878 unsigned lsb = Inst.getOperand(2).getImm();
4879 unsigned widthm1 = Inst.getOperand(3).getImm();
4880 if (widthm1 >= 32 - lsb)
4881 return Error(Operands[5]->getStartLoc(),
4882 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004883 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004884 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004885 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004886 // If we're parsing Thumb2, the .w variant is available and handles
4887 // most cases that are normally illegal for a Thumb1 LDM
4888 // instruction. We'll make the transformation in processInstruction()
4889 // if necessary.
4890 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004891 // Thumb LDM instructions are writeback iff the base register is not
4892 // in the register list.
4893 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004894 bool hasWritebackToken =
4895 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4896 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004897 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004898 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004899 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4900 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004901 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004902 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004903 return Error(Operands[2]->getStartLoc(),
4904 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004905 // If we should not have writeback, there must not be a '!'. This is
4906 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004907 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004908 return Error(Operands[3]->getStartLoc(),
4909 "writeback operator '!' not allowed when base register "
4910 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004911
4912 break;
4913 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004914 case ARM::t2LDMIA_UPD: {
4915 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4916 return Error(Operands[4]->getStartLoc(),
4917 "writeback operator '!' not allowed when base register "
4918 "in register list");
4919 break;
4920 }
Jim Grosbach54026372011-11-10 23:17:11 +00004921 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4922 // so only issue a diagnostic for thumb1. The instructions will be
4923 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004924 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004925 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004926 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4927 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004928 return Error(Operands[2]->getStartLoc(),
4929 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004930 break;
4931 }
4932 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004933 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004934 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4935 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004936 return Error(Operands[2]->getStartLoc(),
4937 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004938 break;
4939 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004940 case ARM::tSTMIA_UPD: {
4941 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004942 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004943 return Error(Operands[4]->getStartLoc(),
4944 "registers must be in range r0-r7");
4945 break;
4946 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004947 }
4948
4949 return false;
4950}
4951
Jim Grosbach84defb52011-12-02 22:34:51 +00004952static unsigned getRealVSTLNOpcode(unsigned Opc) {
4953 switch(Opc) {
4954 default: assert(0 && "unexpected opcode!");
4955 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4956 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4957 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4958 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4959 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4960 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4961 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4962 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4963 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4964 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4965 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4966 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4967 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4968 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4969 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4970 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4971 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4972 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4973 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4974 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4975 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4976 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4977 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4978 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4979 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4980 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4981 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4982 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4983 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4984 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4985 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4986 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4987 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4988 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4989 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4990 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4991 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4992 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4993 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4994 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4995 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4996 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4997 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4998 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4999 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
5000 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
5001 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
5002 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
5003 }
5004}
5005
5006static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005007 switch(Opc) {
5008 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00005009 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
5010 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
5011 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
5012 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
5013 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
5014 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
5015 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
5016 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
5017 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
5018 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
5019 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
5020 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
5021 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
5022 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
5023 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
5024 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
5025 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
5026 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
5027 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
5028 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
5029 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
5030 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
5031 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
5032 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
5033 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
5034 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
5035 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
5036 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
5037 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
5038 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
5039 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
5040 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005041 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
5042 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
5043 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
5044 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
5045 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00005046 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
5047 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
5048 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
5049 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
5050 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005051 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
5052 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
5053 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
5054 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
5055 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
5056 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005057 }
5058}
5059
Jim Grosbach83ec8772011-11-10 23:42:14 +00005060bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005061processInstruction(MCInst &Inst,
5062 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5063 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005064 // Handle NEON VST1 complex aliases.
5065 case ARM::VST1LNdWB_register_Asm_8:
5066 case ARM::VST1LNdWB_register_Asm_P8:
5067 case ARM::VST1LNdWB_register_Asm_I8:
5068 case ARM::VST1LNdWB_register_Asm_S8:
5069 case ARM::VST1LNdWB_register_Asm_U8:
5070 case ARM::VST1LNdWB_register_Asm_16:
5071 case ARM::VST1LNdWB_register_Asm_P16:
5072 case ARM::VST1LNdWB_register_Asm_I16:
5073 case ARM::VST1LNdWB_register_Asm_S16:
5074 case ARM::VST1LNdWB_register_Asm_U16:
5075 case ARM::VST1LNdWB_register_Asm_32:
5076 case ARM::VST1LNdWB_register_Asm_F:
5077 case ARM::VST1LNdWB_register_Asm_F32:
5078 case ARM::VST1LNdWB_register_Asm_I32:
5079 case ARM::VST1LNdWB_register_Asm_S32:
5080 case ARM::VST1LNdWB_register_Asm_U32: {
5081 MCInst TmpInst;
5082 // Shuffle the operands around so the lane index operand is in the
5083 // right place.
5084 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5085 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5086 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5087 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5088 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5089 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5090 TmpInst.addOperand(Inst.getOperand(1)); // lane
5091 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5092 TmpInst.addOperand(Inst.getOperand(6));
5093 Inst = TmpInst;
5094 return true;
5095 }
5096 case ARM::VST1LNdWB_fixed_Asm_8:
5097 case ARM::VST1LNdWB_fixed_Asm_P8:
5098 case ARM::VST1LNdWB_fixed_Asm_I8:
5099 case ARM::VST1LNdWB_fixed_Asm_S8:
5100 case ARM::VST1LNdWB_fixed_Asm_U8:
5101 case ARM::VST1LNdWB_fixed_Asm_16:
5102 case ARM::VST1LNdWB_fixed_Asm_P16:
5103 case ARM::VST1LNdWB_fixed_Asm_I16:
5104 case ARM::VST1LNdWB_fixed_Asm_S16:
5105 case ARM::VST1LNdWB_fixed_Asm_U16:
5106 case ARM::VST1LNdWB_fixed_Asm_32:
5107 case ARM::VST1LNdWB_fixed_Asm_F:
5108 case ARM::VST1LNdWB_fixed_Asm_F32:
5109 case ARM::VST1LNdWB_fixed_Asm_I32:
5110 case ARM::VST1LNdWB_fixed_Asm_S32:
5111 case ARM::VST1LNdWB_fixed_Asm_U32: {
5112 MCInst TmpInst;
5113 // Shuffle the operands around so the lane index operand is in the
5114 // right place.
5115 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5116 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5117 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5118 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5119 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5120 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5121 TmpInst.addOperand(Inst.getOperand(1)); // lane
5122 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5123 TmpInst.addOperand(Inst.getOperand(5));
5124 Inst = TmpInst;
5125 return true;
5126 }
5127 case ARM::VST1LNdAsm_8:
5128 case ARM::VST1LNdAsm_P8:
5129 case ARM::VST1LNdAsm_I8:
5130 case ARM::VST1LNdAsm_S8:
5131 case ARM::VST1LNdAsm_U8:
5132 case ARM::VST1LNdAsm_16:
5133 case ARM::VST1LNdAsm_P16:
5134 case ARM::VST1LNdAsm_I16:
5135 case ARM::VST1LNdAsm_S16:
5136 case ARM::VST1LNdAsm_U16:
5137 case ARM::VST1LNdAsm_32:
5138 case ARM::VST1LNdAsm_F:
5139 case ARM::VST1LNdAsm_F32:
5140 case ARM::VST1LNdAsm_I32:
5141 case ARM::VST1LNdAsm_S32:
5142 case ARM::VST1LNdAsm_U32: {
5143 MCInst TmpInst;
5144 // Shuffle the operands around so the lane index operand is in the
5145 // right place.
5146 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5147 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5148 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5149 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5150 TmpInst.addOperand(Inst.getOperand(1)); // lane
5151 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5152 TmpInst.addOperand(Inst.getOperand(5));
5153 Inst = TmpInst;
5154 return true;
5155 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005156 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005157 case ARM::VLD1LNdWB_register_Asm_8:
5158 case ARM::VLD1LNdWB_register_Asm_P8:
5159 case ARM::VLD1LNdWB_register_Asm_I8:
5160 case ARM::VLD1LNdWB_register_Asm_S8:
5161 case ARM::VLD1LNdWB_register_Asm_U8:
5162 case ARM::VLD1LNdWB_register_Asm_16:
5163 case ARM::VLD1LNdWB_register_Asm_P16:
5164 case ARM::VLD1LNdWB_register_Asm_I16:
5165 case ARM::VLD1LNdWB_register_Asm_S16:
5166 case ARM::VLD1LNdWB_register_Asm_U16:
5167 case ARM::VLD1LNdWB_register_Asm_32:
5168 case ARM::VLD1LNdWB_register_Asm_F:
5169 case ARM::VLD1LNdWB_register_Asm_F32:
5170 case ARM::VLD1LNdWB_register_Asm_I32:
5171 case ARM::VLD1LNdWB_register_Asm_S32:
5172 case ARM::VLD1LNdWB_register_Asm_U32: {
5173 MCInst TmpInst;
5174 // Shuffle the operands around so the lane index operand is in the
5175 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005176 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005177 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5178 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5179 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5180 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5181 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5182 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5183 TmpInst.addOperand(Inst.getOperand(1)); // lane
5184 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5185 TmpInst.addOperand(Inst.getOperand(6));
5186 Inst = TmpInst;
5187 return true;
5188 }
5189 case ARM::VLD1LNdWB_fixed_Asm_8:
5190 case ARM::VLD1LNdWB_fixed_Asm_P8:
5191 case ARM::VLD1LNdWB_fixed_Asm_I8:
5192 case ARM::VLD1LNdWB_fixed_Asm_S8:
5193 case ARM::VLD1LNdWB_fixed_Asm_U8:
5194 case ARM::VLD1LNdWB_fixed_Asm_16:
5195 case ARM::VLD1LNdWB_fixed_Asm_P16:
5196 case ARM::VLD1LNdWB_fixed_Asm_I16:
5197 case ARM::VLD1LNdWB_fixed_Asm_S16:
5198 case ARM::VLD1LNdWB_fixed_Asm_U16:
5199 case ARM::VLD1LNdWB_fixed_Asm_32:
5200 case ARM::VLD1LNdWB_fixed_Asm_F:
5201 case ARM::VLD1LNdWB_fixed_Asm_F32:
5202 case ARM::VLD1LNdWB_fixed_Asm_I32:
5203 case ARM::VLD1LNdWB_fixed_Asm_S32:
5204 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5205 MCInst TmpInst;
5206 // Shuffle the operands around so the lane index operand is in the
5207 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005208 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005209 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5210 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5211 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5212 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5213 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5214 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5215 TmpInst.addOperand(Inst.getOperand(1)); // lane
5216 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5217 TmpInst.addOperand(Inst.getOperand(5));
5218 Inst = TmpInst;
5219 return true;
5220 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005221 case ARM::VLD1LNdAsm_8:
5222 case ARM::VLD1LNdAsm_P8:
5223 case ARM::VLD1LNdAsm_I8:
5224 case ARM::VLD1LNdAsm_S8:
5225 case ARM::VLD1LNdAsm_U8:
5226 case ARM::VLD1LNdAsm_16:
5227 case ARM::VLD1LNdAsm_P16:
5228 case ARM::VLD1LNdAsm_I16:
5229 case ARM::VLD1LNdAsm_S16:
5230 case ARM::VLD1LNdAsm_U16:
5231 case ARM::VLD1LNdAsm_32:
5232 case ARM::VLD1LNdAsm_F:
5233 case ARM::VLD1LNdAsm_F32:
5234 case ARM::VLD1LNdAsm_I32:
5235 case ARM::VLD1LNdAsm_S32:
5236 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005237 MCInst TmpInst;
5238 // Shuffle the operands around so the lane index operand is in the
5239 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005240 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005241 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5242 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5243 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5244 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5245 TmpInst.addOperand(Inst.getOperand(1)); // lane
5246 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5247 TmpInst.addOperand(Inst.getOperand(5));
5248 Inst = TmpInst;
5249 return true;
5250 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005251 // Handle the Thumb2 mode MOV complex aliases.
5252 case ARM::t2MOVsi:
5253 case ARM::t2MOVSsi: {
5254 // Which instruction to expand to depends on the CCOut operand and
5255 // whether we're in an IT block if the register operands are low
5256 // registers.
5257 bool isNarrow = false;
5258 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5259 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5260 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5261 isNarrow = true;
5262 MCInst TmpInst;
5263 unsigned newOpc;
5264 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5265 default: llvm_unreachable("unexpected opcode!");
5266 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5267 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5268 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5269 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5270 }
5271 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5272 if (Ammount == 32) Ammount = 0;
5273 TmpInst.setOpcode(newOpc);
5274 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5275 if (isNarrow)
5276 TmpInst.addOperand(MCOperand::CreateReg(
5277 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5278 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5279 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5280 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5281 TmpInst.addOperand(Inst.getOperand(4));
5282 if (!isNarrow)
5283 TmpInst.addOperand(MCOperand::CreateReg(
5284 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5285 Inst = TmpInst;
5286 return true;
5287 }
5288 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005289 case ARM::ASRr:
5290 case ARM::LSRr:
5291 case ARM::LSLr:
5292 case ARM::RORr: {
5293 ARM_AM::ShiftOpc ShiftTy;
5294 switch(Inst.getOpcode()) {
5295 default: llvm_unreachable("unexpected opcode!");
5296 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5297 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5298 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5299 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5300 }
5301 // A shift by zero is a plain MOVr, not a MOVsi.
5302 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5303 MCInst TmpInst;
5304 TmpInst.setOpcode(ARM::MOVsr);
5305 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5306 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5307 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5308 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5309 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5310 TmpInst.addOperand(Inst.getOperand(4));
5311 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5312 Inst = TmpInst;
5313 return true;
5314 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005315 case ARM::ASRi:
5316 case ARM::LSRi:
5317 case ARM::LSLi:
5318 case ARM::RORi: {
5319 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005320 switch(Inst.getOpcode()) {
5321 default: llvm_unreachable("unexpected opcode!");
5322 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5323 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5324 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5325 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5326 }
5327 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005328 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005329 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5330 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005331 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005332 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005333 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5334 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005335 if (Opc == ARM::MOVsi)
5336 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005337 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5338 TmpInst.addOperand(Inst.getOperand(4));
5339 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5340 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005341 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005342 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005343 case ARM::RRXi: {
5344 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5345 MCInst TmpInst;
5346 TmpInst.setOpcode(ARM::MOVsi);
5347 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5348 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5349 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5350 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5351 TmpInst.addOperand(Inst.getOperand(3));
5352 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5353 Inst = TmpInst;
5354 return true;
5355 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005356 case ARM::t2LDMIA_UPD: {
5357 // If this is a load of a single register, then we should use
5358 // a post-indexed LDR instruction instead, per the ARM ARM.
5359 if (Inst.getNumOperands() != 5)
5360 return false;
5361 MCInst TmpInst;
5362 TmpInst.setOpcode(ARM::t2LDR_POST);
5363 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5364 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5365 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5366 TmpInst.addOperand(MCOperand::CreateImm(4));
5367 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5368 TmpInst.addOperand(Inst.getOperand(3));
5369 Inst = TmpInst;
5370 return true;
5371 }
5372 case ARM::t2STMDB_UPD: {
5373 // If this is a store of a single register, then we should use
5374 // a pre-indexed STR instruction instead, per the ARM ARM.
5375 if (Inst.getNumOperands() != 5)
5376 return false;
5377 MCInst TmpInst;
5378 TmpInst.setOpcode(ARM::t2STR_PRE);
5379 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5380 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5381 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5382 TmpInst.addOperand(MCOperand::CreateImm(-4));
5383 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5384 TmpInst.addOperand(Inst.getOperand(3));
5385 Inst = TmpInst;
5386 return true;
5387 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005388 case ARM::LDMIA_UPD:
5389 // If this is a load of a single register via a 'pop', then we should use
5390 // a post-indexed LDR instruction instead, per the ARM ARM.
5391 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5392 Inst.getNumOperands() == 5) {
5393 MCInst TmpInst;
5394 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5395 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5396 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5397 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5398 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5399 TmpInst.addOperand(MCOperand::CreateImm(4));
5400 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5401 TmpInst.addOperand(Inst.getOperand(3));
5402 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005403 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005404 }
5405 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005406 case ARM::STMDB_UPD:
5407 // If this is a store of a single register via a 'push', then we should use
5408 // a pre-indexed STR instruction instead, per the ARM ARM.
5409 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5410 Inst.getNumOperands() == 5) {
5411 MCInst TmpInst;
5412 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5413 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5414 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5415 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5416 TmpInst.addOperand(MCOperand::CreateImm(-4));
5417 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5418 TmpInst.addOperand(Inst.getOperand(3));
5419 Inst = TmpInst;
5420 }
5421 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005422 case ARM::t2ADDri12:
5423 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5424 // mnemonic was used (not "addw"), encoding T3 is preferred.
5425 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5426 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5427 break;
5428 Inst.setOpcode(ARM::t2ADDri);
5429 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5430 break;
5431 case ARM::t2SUBri12:
5432 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5433 // mnemonic was used (not "subw"), encoding T3 is preferred.
5434 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5435 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5436 break;
5437 Inst.setOpcode(ARM::t2SUBri);
5438 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5439 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005440 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005441 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5442 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5443 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5444 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005445 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005446 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005447 return true;
5448 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005449 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005450 case ARM::tSUBi8:
5451 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5452 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5453 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5454 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005455 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005456 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005457 return true;
5458 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005459 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005460 case ARM::t2ADDrr: {
5461 // If the destination and first source operand are the same, and
5462 // there's no setting of the flags, use encoding T2 instead of T3.
5463 // Note that this is only for ADD, not SUB. This mirrors the system
5464 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5465 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5466 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005467 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5468 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005469 break;
5470 MCInst TmpInst;
5471 TmpInst.setOpcode(ARM::tADDhirr);
5472 TmpInst.addOperand(Inst.getOperand(0));
5473 TmpInst.addOperand(Inst.getOperand(0));
5474 TmpInst.addOperand(Inst.getOperand(2));
5475 TmpInst.addOperand(Inst.getOperand(3));
5476 TmpInst.addOperand(Inst.getOperand(4));
5477 Inst = TmpInst;
5478 return true;
5479 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005480 case ARM::tB:
5481 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005482 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005483 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005484 return true;
5485 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005486 break;
5487 case ARM::t2B:
5488 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005489 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005490 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005491 return true;
5492 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005493 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005494 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005495 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005496 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005497 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005498 return true;
5499 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005500 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005501 case ARM::tBcc:
5502 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005503 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005504 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005505 return true;
5506 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005507 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005508 case ARM::tLDMIA: {
5509 // If the register list contains any high registers, or if the writeback
5510 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5511 // instead if we're in Thumb2. Otherwise, this should have generated
5512 // an error in validateInstruction().
5513 unsigned Rn = Inst.getOperand(0).getReg();
5514 bool hasWritebackToken =
5515 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5516 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5517 bool listContainsBase;
5518 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5519 (!listContainsBase && !hasWritebackToken) ||
5520 (listContainsBase && hasWritebackToken)) {
5521 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5522 assert (isThumbTwo());
5523 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5524 // If we're switching to the updating version, we need to insert
5525 // the writeback tied operand.
5526 if (hasWritebackToken)
5527 Inst.insert(Inst.begin(),
5528 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005529 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005530 }
5531 break;
5532 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005533 case ARM::tSTMIA_UPD: {
5534 // If the register list contains any high registers, we need to use
5535 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5536 // should have generated an error in validateInstruction().
5537 unsigned Rn = Inst.getOperand(0).getReg();
5538 bool listContainsBase;
5539 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5540 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5541 assert (isThumbTwo());
5542 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005543 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005544 }
5545 break;
5546 }
Jim Grosbach54026372011-11-10 23:17:11 +00005547 case ARM::tPOP: {
5548 bool listContainsBase;
5549 // If the register list contains any high registers, we need to use
5550 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5551 // should have generated an error in validateInstruction().
5552 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005553 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005554 assert (isThumbTwo());
5555 Inst.setOpcode(ARM::t2LDMIA_UPD);
5556 // Add the base register and writeback operands.
5557 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5558 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005559 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005560 }
5561 case ARM::tPUSH: {
5562 bool listContainsBase;
5563 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005564 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005565 assert (isThumbTwo());
5566 Inst.setOpcode(ARM::t2STMDB_UPD);
5567 // Add the base register and writeback operands.
5568 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5569 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005570 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005571 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005572 case ARM::t2MOVi: {
5573 // If we can use the 16-bit encoding and the user didn't explicitly
5574 // request the 32-bit variant, transform it here.
5575 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5576 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005577 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5578 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5579 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005580 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5581 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5582 // The operands aren't in the same order for tMOVi8...
5583 MCInst TmpInst;
5584 TmpInst.setOpcode(ARM::tMOVi8);
5585 TmpInst.addOperand(Inst.getOperand(0));
5586 TmpInst.addOperand(Inst.getOperand(4));
5587 TmpInst.addOperand(Inst.getOperand(1));
5588 TmpInst.addOperand(Inst.getOperand(2));
5589 TmpInst.addOperand(Inst.getOperand(3));
5590 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005591 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005592 }
5593 break;
5594 }
5595 case ARM::t2MOVr: {
5596 // If we can use the 16-bit encoding and the user didn't explicitly
5597 // request the 32-bit variant, transform it here.
5598 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5599 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5600 Inst.getOperand(2).getImm() == ARMCC::AL &&
5601 Inst.getOperand(4).getReg() == ARM::CPSR &&
5602 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5603 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5604 // The operands aren't the same for tMOV[S]r... (no cc_out)
5605 MCInst TmpInst;
5606 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5607 TmpInst.addOperand(Inst.getOperand(0));
5608 TmpInst.addOperand(Inst.getOperand(1));
5609 TmpInst.addOperand(Inst.getOperand(2));
5610 TmpInst.addOperand(Inst.getOperand(3));
5611 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005612 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005613 }
5614 break;
5615 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005616 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005617 case ARM::t2SXTB:
5618 case ARM::t2UXTH:
5619 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005620 // If we can use the 16-bit encoding and the user didn't explicitly
5621 // request the 32-bit variant, transform it here.
5622 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5623 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5624 Inst.getOperand(2).getImm() == 0 &&
5625 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5626 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005627 unsigned NewOpc;
5628 switch (Inst.getOpcode()) {
5629 default: llvm_unreachable("Illegal opcode!");
5630 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5631 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5632 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5633 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5634 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005635 // The operands aren't the same for thumb1 (no rotate operand).
5636 MCInst TmpInst;
5637 TmpInst.setOpcode(NewOpc);
5638 TmpInst.addOperand(Inst.getOperand(0));
5639 TmpInst.addOperand(Inst.getOperand(1));
5640 TmpInst.addOperand(Inst.getOperand(3));
5641 TmpInst.addOperand(Inst.getOperand(4));
5642 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005643 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005644 }
5645 break;
5646 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005647 case ARM::t2IT: {
5648 // The mask bits for all but the first condition are represented as
5649 // the low bit of the condition code value implies 't'. We currently
5650 // always have 1 implies 't', so XOR toggle the bits if the low bit
5651 // of the condition code is zero. The encoding also expects the low
5652 // bit of the condition to be encoded as bit 4 of the mask operand,
5653 // so mask that in if needed
5654 MCOperand &MO = Inst.getOperand(1);
5655 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005656 unsigned OrigMask = Mask;
5657 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005658 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005659 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5660 for (unsigned i = 3; i != TZ; --i)
5661 Mask ^= 1 << i;
5662 } else
5663 Mask |= 0x10;
5664 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005665
5666 // Set up the IT block state according to the IT instruction we just
5667 // matched.
5668 assert(!inITBlock() && "nested IT blocks?!");
5669 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5670 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5671 ITState.CurPosition = 0;
5672 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005673 break;
5674 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005675 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005676 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005677}
5678
Jim Grosbach47a0d522011-08-16 20:45:50 +00005679unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5680 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5681 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005682 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005683 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005684 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5685 assert(MCID.hasOptionalDef() &&
5686 "optionally flag setting instruction missing optional def operand");
5687 assert(MCID.NumOperands == Inst.getNumOperands() &&
5688 "operand count mismatch!");
5689 // Find the optional-def operand (cc_out).
5690 unsigned OpNo;
5691 for (OpNo = 0;
5692 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5693 ++OpNo)
5694 ;
5695 // If we're parsing Thumb1, reject it completely.
5696 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5697 return Match_MnemonicFail;
5698 // If we're parsing Thumb2, which form is legal depends on whether we're
5699 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005700 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5701 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005702 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005703 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5704 inITBlock())
5705 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005706 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005707 // Some high-register supporting Thumb1 encodings only allow both registers
5708 // to be from r0-r7 when in Thumb2.
5709 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5710 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5711 isARMLowRegister(Inst.getOperand(2).getReg()))
5712 return Match_RequiresThumb2;
5713 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005714 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005715 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5716 isARMLowRegister(Inst.getOperand(1).getReg()))
5717 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005718 return Match_Success;
5719}
5720
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005721bool ARMAsmParser::
5722MatchAndEmitInstruction(SMLoc IDLoc,
5723 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5724 MCStreamer &Out) {
5725 MCInst Inst;
5726 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005727 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005728 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005729 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005730 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005731 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005732 // Context sensitive operand constraints aren't handled by the matcher,
5733 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005734 if (validateInstruction(Inst, Operands)) {
5735 // Still progress the IT block, otherwise one wrong condition causes
5736 // nasty cascading errors.
5737 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005738 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005739 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005740
Jim Grosbachf8fce712011-08-11 17:35:48 +00005741 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005742 // encoding is selected. Loop on it while changes happen so the
5743 // individual transformations can chain off each other. E.g.,
5744 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5745 while (processInstruction(Inst, Operands))
5746 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005747
Jim Grosbacha1109882011-09-02 23:22:08 +00005748 // Only move forward at the very end so that everything in validate
5749 // and process gets a consistent answer about whether we're in an IT
5750 // block.
5751 forwardITPosition();
5752
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005753 Out.EmitInstruction(Inst);
5754 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005755 case Match_MissingFeature:
5756 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5757 return true;
5758 case Match_InvalidOperand: {
5759 SMLoc ErrorLoc = IDLoc;
5760 if (ErrorInfo != ~0U) {
5761 if (ErrorInfo >= Operands.size())
5762 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005763
Chris Lattnere73d4f82010-10-28 21:41:58 +00005764 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5765 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5766 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005767
Chris Lattnere73d4f82010-10-28 21:41:58 +00005768 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005769 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005770 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005771 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005772 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005773 // The converter function will have already emited a diagnostic.
5774 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005775 case Match_RequiresNotITBlock:
5776 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005777 case Match_RequiresITBlock:
5778 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005779 case Match_RequiresV6:
5780 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5781 case Match_RequiresThumb2:
5782 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005783 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005784
Eric Christopherc223e2b2010-10-29 09:26:59 +00005785 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005786 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005787}
5788
Jim Grosbach1355cf12011-07-26 17:10:22 +00005789/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005790bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5791 StringRef IDVal = DirectiveID.getIdentifier();
5792 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005793 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005794 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005795 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005796 else if (IDVal == ".arm")
5797 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005798 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005799 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005800 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005801 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005802 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005803 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005804 return true;
5805}
5806
Jim Grosbach1355cf12011-07-26 17:10:22 +00005807/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005808/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005809bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005810 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5811 for (;;) {
5812 const MCExpr *Value;
5813 if (getParser().ParseExpression(Value))
5814 return true;
5815
Chris Lattneraaec2052010-01-19 19:46:13 +00005816 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005817
5818 if (getLexer().is(AsmToken::EndOfStatement))
5819 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005820
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005821 // FIXME: Improve diagnostic.
5822 if (getLexer().isNot(AsmToken::Comma))
5823 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005824 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005825 }
5826 }
5827
Sean Callananb9a25b72010-01-19 20:27:46 +00005828 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005829 return false;
5830}
5831
Jim Grosbach1355cf12011-07-26 17:10:22 +00005832/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005833/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005834bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005835 if (getLexer().isNot(AsmToken::EndOfStatement))
5836 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005837 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005838
Jim Grosbach9a70df92011-12-07 18:04:19 +00005839 if (!isThumb())
5840 SwitchMode();
5841 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5842 return false;
5843}
5844
5845/// parseDirectiveARM
5846/// ::= .arm
5847bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5848 if (getLexer().isNot(AsmToken::EndOfStatement))
5849 return Error(L, "unexpected token in directive");
5850 Parser.Lex();
5851
5852 if (isThumb())
5853 SwitchMode();
5854 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005855 return false;
5856}
5857
Jim Grosbach1355cf12011-07-26 17:10:22 +00005858/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005859/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005860bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005861 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5862 bool isMachO = MAI.hasSubsectionsViaSymbols();
5863 StringRef Name;
5864
5865 // Darwin asm has function name after .thumb_func direction
5866 // ELF doesn't
5867 if (isMachO) {
5868 const AsmToken &Tok = Parser.getTok();
5869 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5870 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005871 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005872 Parser.Lex(); // Consume the identifier token.
5873 }
5874
Jim Grosbachd475f862011-11-10 20:48:53 +00005875 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005876 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005877 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005878
Rafael Espindola64695402011-05-16 16:17:21 +00005879 // FIXME: assuming function name will be the line following .thumb_func
5880 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005881 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005882 }
5883
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005884 // Mark symbol as a thumb symbol.
5885 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5886 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005887 return false;
5888}
5889
Jim Grosbach1355cf12011-07-26 17:10:22 +00005890/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005891/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005892bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005893 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005894 if (Tok.isNot(AsmToken::Identifier))
5895 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005896 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005897 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005898 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005899 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005900 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005901 else
5902 return Error(L, "unrecognized syntax mode in .syntax directive");
5903
5904 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005905 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005906 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005907
5908 // TODO tell the MC streamer the mode
5909 // getParser().getStreamer().Emit???();
5910 return false;
5911}
5912
Jim Grosbach1355cf12011-07-26 17:10:22 +00005913/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005914/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005915bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005916 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005917 if (Tok.isNot(AsmToken::Integer))
5918 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005919 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005920 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005921 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005922 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005923 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005924 else
5925 return Error(L, "invalid operand to .code directive");
5926
5927 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005928 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005929 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005930
Evan Cheng32869202011-07-08 22:36:29 +00005931 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005932 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005933 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005934 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005935 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005936 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005937 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005938 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005939 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005940
Kevin Enderby515d5092009-10-15 20:48:48 +00005941 return false;
5942}
5943
Sean Callanan90b70972010-04-07 20:29:34 +00005944extern "C" void LLVMInitializeARMAsmLexer();
5945
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005946/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005947extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005948 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5949 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005950 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005951}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005952
Chris Lattner0692ee62010-09-06 19:11:01 +00005953#define GET_REGISTER_MATCHER
5954#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005955#include "ARMGenAsmMatcher.inc"