blob: 33b7eef67c6fabb4f1fc50676eb2c9ff3a8a7f99 [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);
95 bool parseDirectiveThumbFunc(SMLoc L);
96 bool parseDirectiveCode(SMLoc L);
97 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000098
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000100 bool &CarrySetting, unsigned &ProcessorIMod,
101 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000102 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000103 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000104
Evan Chengebdeeab2011-07-08 01:53:10 +0000105 bool isThumb() const {
106 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000107 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000110 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000111 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000112 bool isThumbTwo() const {
113 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
114 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000115 bool hasV6Ops() const {
116 return STI.getFeatureBits() & ARM::HasV6Ops;
117 }
James Molloyacad68d2011-09-28 14:21:38 +0000118 bool hasV7Ops() const {
119 return STI.getFeatureBits() & ARM::HasV7Ops;
120 }
Evan Cheng32869202011-07-08 22:36:29 +0000121 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000122 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
123 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000124 }
James Molloyacad68d2011-09-28 14:21:38 +0000125 bool isMClass() const {
126 return STI.getFeatureBits() & ARM::FeatureMClass;
127 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000128
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000129 /// @name Auto-generated Match Functions
130 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000131
Chris Lattner0692ee62010-09-06 19:11:01 +0000132#define GET_ASSEMBLER_HEADER
133#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135 /// }
136
Jim Grosbach89df9962011-08-26 21:43:41 +0000137 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000140 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000142 OperandMatchResultTy parseCoprocOptionOperand(
143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000150 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
151 StringRef Op, int Low, int High);
152 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "lsl", 0, 31);
154 }
155 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
156 return parsePKHImm(O, "asr", 1, 32);
157 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000158 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000159 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000160 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000161 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000162 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000163 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000164 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000165 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000166 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000167
168 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000169 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
171 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000173 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000175 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000177 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000179 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000181 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000183 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000185 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000187 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
193 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000195 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000197 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000199 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000201 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000203 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
205 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000207 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
209 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000211
212 bool validateInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000214 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000215 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000216 bool shouldOmitCCOutOperand(StringRef Mnemonic,
217 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000218
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000219public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000220 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000221 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000223 Match_RequiresV6,
224 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000225 };
226
Evan Chengffc0e732011-07-09 05:47:46 +0000227 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000228 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000229 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000230
Evan Chengebdeeab2011-07-08 01:53:10 +0000231 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000233
234 // Not in an ITBlock to start with.
235 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000236 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000237
Jim Grosbach1355cf12011-07-26 17:10:22 +0000238 // Implementation of the MCTargetAsmParser interface:
239 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
240 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000241 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000242 bool ParseDirective(AsmToken DirectiveID);
243
Jim Grosbach47a0d522011-08-16 20:45:50 +0000244 unsigned checkTargetMatchPredicate(MCInst &Inst);
245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 bool MatchAndEmitInstruction(SMLoc IDLoc,
247 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
248 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000249};
Jim Grosbach16c74252010-10-29 14:46:02 +0000250} // end anonymous namespace
251
Chris Lattner3a697562010-10-28 17:20:03 +0000252namespace {
253
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000254/// ARMOperand - Instances of this class represent a parsed ARM machine
255/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000256class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000257 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_CondCode,
259 k_CCOut,
260 k_ITCondMask,
261 k_CoprocNum,
262 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000263 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000264 k_Immediate,
265 k_FPImmediate,
266 k_MemBarrierOpt,
267 k_Memory,
268 k_PostIndexRegister,
269 k_MSRMask,
270 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000271 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Register,
273 k_RegisterList,
274 k_DPRRegisterList,
275 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000276 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000277 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000278 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_ShiftedRegister,
280 k_ShiftedImmediate,
281 k_ShifterImmediate,
282 k_RotateImmediate,
283 k_BitfieldDescriptor,
284 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000285 } Kind;
286
Sean Callanan76264762010-04-02 22:27:05 +0000287 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000288 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000289
290 union {
291 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000292 ARMCC::CondCodes Val;
293 } CC;
294
295 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000296 unsigned Val;
297 } Cop;
298
299 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000300 unsigned Val;
301 } CoprocOption;
302
303 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000304 unsigned Mask:4;
305 } ITMask;
306
307 struct {
308 ARM_MB::MemBOpt Val;
309 } MBOpt;
310
311 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000312 ARM_PROC::IFlags Val;
313 } IFlags;
314
315 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000316 unsigned Val;
317 } MMask;
318
319 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000320 const char *Data;
321 unsigned Length;
322 } Tok;
323
324 struct {
325 unsigned RegNum;
326 } Reg;
327
Jim Grosbach862019c2011-10-18 23:02:30 +0000328 // A vector register list is a sequential list of 1 to 4 registers.
329 struct {
330 unsigned RegNum;
331 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000332 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000333 } VectorList;
334
Bill Wendling8155e5b2010-11-06 22:19:43 +0000335 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000336 unsigned Val;
337 } VectorIndex;
338
339 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000340 const MCExpr *Val;
341 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000342
Jim Grosbach9d390362011-10-03 23:38:36 +0000343 struct {
344 unsigned Val; // encoded 8-bit representation
345 } FPImm;
346
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000347 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000348 struct {
349 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000350 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
351 // was specified.
352 const MCConstantExpr *OffsetImm; // Offset immediate value
353 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
354 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000355 unsigned ShiftImm; // shift for OffsetReg.
356 unsigned Alignment; // 0 = no alignment specified
357 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000358 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000359 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000360
361 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000363 bool isAdd;
364 ARM_AM::ShiftOpc ShiftTy;
365 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 } PostIdxReg;
367
368 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000369 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000370 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000371 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftReg;
376 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000377 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000378 struct {
379 ARM_AM::ShiftOpc ShiftTy;
380 unsigned SrcReg;
381 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000382 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000383 struct {
384 unsigned Imm;
385 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000386 struct {
387 unsigned LSB;
388 unsigned Width;
389 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000390 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000391
Bill Wendling146018f2010-11-06 21:42:12 +0000392 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
393public:
Sean Callanan76264762010-04-02 22:27:05 +0000394 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
395 Kind = o.Kind;
396 StartLoc = o.StartLoc;
397 EndLoc = o.EndLoc;
398 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000400 CC = o.CC;
401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000403 ITMask = o.ITMask;
404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000405 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000406 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000407 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CCOut:
409 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000410 Reg = o.Reg;
411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_RegisterList:
413 case k_DPRRegisterList:
414 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000415 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000416 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000417 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000418 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000419 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000420 VectorList = o.VectorList;
421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_CoprocNum:
423 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000424 Cop = o.Cop;
425 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000426 case k_CoprocOption:
427 CoprocOption = o.CoprocOption;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000430 Imm = o.Imm;
431 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000432 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000433 FPImm = o.FPImm;
434 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000435 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000436 MBOpt = o.MBOpt;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000439 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000442 PostIdxReg = o.PostIdxReg;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000445 MMask = o.MMask;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000448 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000451 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000454 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000457 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000460 RotImm = o.RotImm;
461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000463 Bitfield = o.Bitfield;
464 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000465 case k_VectorIndex:
466 VectorIndex = o.VectorIndex;
467 break;
Sean Callanan76264762010-04-02 22:27:05 +0000468 }
469 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000470
Sean Callanan76264762010-04-02 22:27:05 +0000471 /// getStartLoc - Get the location of the first token of this operand.
472 SMLoc getStartLoc() const { return StartLoc; }
473 /// getEndLoc - Get the location of the last token of this operand.
474 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475
Daniel Dunbar8462b302010-08-11 06:36:53 +0000476 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000478 return CC.Val;
479 }
480
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000481 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000483 return Cop.Val;
484 }
485
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000488 return StringRef(Tok.Data, Tok.Length);
489 }
490
491 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000493 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000494 }
495
Bill Wendling5fa22a12010-11-09 23:28:44 +0000496 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
498 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000499 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000500 }
501
Kevin Enderbycfe07242009-10-13 22:19:02 +0000502 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000504 return Imm.Val;
505 }
506
Jim Grosbach9d390362011-10-03 23:38:36 +0000507 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000508 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000509 return FPImm.Val;
510 }
511
Jim Grosbach460a9052011-10-07 23:56:00 +0000512 unsigned getVectorIndex() const {
513 assert(Kind == k_VectorIndex && "Invalid access!");
514 return VectorIndex.Val;
515 }
516
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000517 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000518 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000519 return MBOpt.Val;
520 }
521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000522 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000523 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000524 return IFlags.Val;
525 }
526
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000527 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000529 return MMask.Val;
530 }
531
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 bool isCoprocNum() const { return Kind == k_CoprocNum; }
533 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000534 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 bool isCondCode() const { return Kind == k_CondCode; }
536 bool isCCOut() const { return Kind == k_CCOut; }
537 bool isITMask() const { return Kind == k_ITCondMask; }
538 bool isITCondCode() const { return Kind == k_CondCode; }
539 bool isImm() const { return Kind == k_Immediate; }
540 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000541 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
548 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000549 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
556 }
557 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
564 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000565 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 256;
572 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000573 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000574 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000575 return false;
576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
577 if (!CE) return false;
578 int64_t Value = CE->getValue();
579 return Value >= 0 && Value < 8;
580 }
581 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000583 return false;
584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 16;
588 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000589 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000591 return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = CE->getValue();
595 return Value >= 0 && Value < 32;
596 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000597 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000599 return false;
600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value > 0 && Value < 17;
604 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000605 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value > 0 && Value < 33;
612 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000613 bool isImm0_32() const {
614 if (Kind != k_Immediate)
615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value >= 0 && Value < 33;
620 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000621 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 65536;
628 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000629 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000630 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000631 return false;
632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
633 // If it's not a constant expression, it'll generate a fixup and be
634 // handled later.
635 if (!CE) return true;
636 int64_t Value = CE->getValue();
637 return Value >= 0 && Value < 65536;
638 }
Jim Grosbached838482011-07-26 16:24:27 +0000639 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000641 return false;
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value >= 0 && Value <= 0xffffff;
646 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000647 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000649 return false;
650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value < 33;
654 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000655 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return Value >= 0 && Value < 32;
662 }
663 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return Value > 0 && Value <= 32;
670 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000671 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000672 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000673 return false;
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
675 if (!CE) return false;
676 int64_t Value = CE->getValue();
677 return ARM_AM::getSOImmVal(Value) != -1;
678 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000679 bool isARMSOImmNot() const {
680 if (Kind != k_Immediate)
681 return false;
682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return ARM_AM::getSOImmVal(~Value) != -1;
686 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000687 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000688 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return ARM_AM::getT2SOImmVal(Value) != -1;
694 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000695 bool isT2SOImmNot() const {
696 if (Kind != k_Immediate)
697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return ARM_AM::getT2SOImmVal(~Value) != -1;
702 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000703 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000704 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000705 return false;
706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value == 1 || Value == 0;
710 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 bool isReg() const { return Kind == k_Register; }
712 bool isRegList() const { return Kind == k_RegisterList; }
713 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
714 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
715 bool isToken() const { return Kind == k_Token; }
716 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
717 bool isMemory() const { return Kind == k_Memory; }
718 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
719 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
720 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
721 bool isRotImm() const { return Kind == k_RotateImmediate; }
722 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
723 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000724 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000725 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000726 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000727 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000728 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000729 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000730 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000731 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
732 (alignOK || Memory.Alignment == 0);
733 }
734 bool isAlignedMemory() const {
735 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000736 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000737 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000738 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000739 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000740 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000741 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000742 if (!Memory.OffsetImm) return true;
743 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000744 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000745 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000746 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000747 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000748 return false;
749 // Immediate offset in range [-4095, 4095].
750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Val = CE->getValue();
753 return Val > -4096 && Val < 4096;
754 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000755 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000756 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000757 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000758 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000759 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000760 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000761 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000762 if (!Memory.OffsetImm) return true;
763 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000764 return Val > -256 && Val < 256;
765 }
766 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000767 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000768 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000770 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
771 // Immediate offset in range [-255, 255].
772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
773 if (!CE) return false;
774 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000775 // Special case, #-0 is INT32_MIN.
776 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000777 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000778 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000779 // If we have an immediate that's not a constant, treat it as a label
780 // reference needing a fixup. If it is a constant, it's something else
781 // and we reject it.
782 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
783 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000784 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000785 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000787 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000788 if (!Memory.OffsetImm) return true;
789 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000790 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000791 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000792 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000793 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000794 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000795 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000796 return false;
797 return true;
798 }
799 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000800 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000801 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
802 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000803 return false;
804 return true;
805 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000806 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000807 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000808 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000809 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000810 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000811 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000812 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
813 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000814 return false;
815 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000816 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000817 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000818 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000819 return false;
820 return true;
821 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000822 bool isMemThumbRR() const {
823 // Thumb reg+reg addressing is simple. Just two registers, a base and
824 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000825 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000826 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000827 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000828 return isARMLowRegister(Memory.BaseRegNum) &&
829 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000830 }
831 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000832 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000833 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000834 return false;
835 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000836 if (!Memory.OffsetImm) return true;
837 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000838 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
839 }
Jim Grosbach38466302011-08-19 18:55:51 +0000840 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000841 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000842 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000843 return false;
844 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000845 if (!Memory.OffsetImm) return true;
846 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000847 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
848 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000849 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000850 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000851 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000852 return false;
853 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000854 if (!Memory.OffsetImm) return true;
855 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000856 return Val >= 0 && Val <= 31;
857 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000858 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.OffsetRegNum != 0 ||
860 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000861 return false;
862 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000865 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000866 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000867 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000873 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000875 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000877 return false;
878 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000881 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
882 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000883 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000885 return false;
886 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000889 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000890 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000891 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000893 return false;
894 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000897 return Val >= 0 && Val < 256;
898 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000899 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000900 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000901 return false;
902 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000905 return Val > -256 && Val < 0;
906 }
907 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000908 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000909 return false;
910 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000911 if (!Memory.OffsetImm) return true;
912 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000913 return (Val >= 0 && Val < 4096);
914 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000915 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000916 // If we have an immediate that's not a constant, treat it as a label
917 // reference needing a fixup. If it is a constant, it's something else
918 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000919 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000920 return true;
921
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000923 return false;
924 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000925 if (!Memory.OffsetImm) return true;
926 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000927 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 }
929 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000930 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000935 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000936 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000937 bool isPostIdxImm8s4() const {
938 if (Kind != k_Immediate)
939 return false;
940 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
941 if (!CE) return false;
942 int64_t Val = CE->getValue();
943 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
944 (Val == INT32_MIN);
945 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000946
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000947 bool isMSRMask() const { return Kind == k_MSRMask; }
948 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000949
Jim Grosbach0e387b22011-10-17 22:26:03 +0000950 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000951 bool isVecListOneD() const {
952 if (Kind != k_VectorList) return false;
953 return VectorList.Count == 1;
954 }
955
Jim Grosbach280dfad2011-10-21 18:54:25 +0000956 bool isVecListTwoD() const {
957 if (Kind != k_VectorList) return false;
958 return VectorList.Count == 2;
959 }
960
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000961 bool isVecListThreeD() const {
962 if (Kind != k_VectorList) return false;
963 return VectorList.Count == 3;
964 }
965
Jim Grosbachb6310312011-10-21 20:35:01 +0000966 bool isVecListFourD() const {
967 if (Kind != k_VectorList) return false;
968 return VectorList.Count == 4;
969 }
970
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000971 bool isVecListTwoQ() const {
972 if (Kind != k_VectorList) return false;
973 //FIXME: We haven't taught the parser to handle by-two register lists
974 // yet, so don't pretend to know one.
975 return VectorList.Count == 2 && false;
976 }
977
Jim Grosbach98b05a52011-11-30 01:09:44 +0000978 bool isVecListOneDAllLanes() const {
979 if (Kind != k_VectorListAllLanes) return false;
980 return VectorList.Count == 1;
981 }
982
Jim Grosbach13af2222011-11-30 18:21:25 +0000983 bool isVecListTwoDAllLanes() const {
984 if (Kind != k_VectorListAllLanes) return false;
985 return VectorList.Count == 2;
986 }
987
Jim Grosbach7636bf62011-12-02 00:35:16 +0000988 bool isVecListOneDByteIndexed() const {
989 if (Kind != k_VectorListIndexed) return false;
990 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
991 }
992
Jim Grosbach460a9052011-10-07 23:56:00 +0000993 bool isVectorIndex8() const {
994 if (Kind != k_VectorIndex) return false;
995 return VectorIndex.Val < 8;
996 }
997 bool isVectorIndex16() const {
998 if (Kind != k_VectorIndex) return false;
999 return VectorIndex.Val < 4;
1000 }
1001 bool isVectorIndex32() const {
1002 if (Kind != k_VectorIndex) return false;
1003 return VectorIndex.Val < 2;
1004 }
1005
Jim Grosbach0e387b22011-10-17 22:26:03 +00001006 bool isNEONi8splat() const {
1007 if (Kind != k_Immediate)
1008 return false;
1009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1010 // Must be a constant.
1011 if (!CE) return false;
1012 int64_t Value = CE->getValue();
1013 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1014 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001015 return Value >= 0 && Value < 256;
1016 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001017
Jim Grosbachea461102011-10-17 23:09:09 +00001018 bool isNEONi16splat() const {
1019 if (Kind != k_Immediate)
1020 return false;
1021 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1022 // Must be a constant.
1023 if (!CE) return false;
1024 int64_t Value = CE->getValue();
1025 // i16 value in the range [0,255] or [0x0100, 0xff00]
1026 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1027 }
1028
Jim Grosbach6248a542011-10-18 00:22:00 +00001029 bool isNEONi32splat() const {
1030 if (Kind != k_Immediate)
1031 return false;
1032 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1033 // Must be a constant.
1034 if (!CE) return false;
1035 int64_t Value = CE->getValue();
1036 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1037 return (Value >= 0 && Value < 256) ||
1038 (Value >= 0x0100 && Value <= 0xff00) ||
1039 (Value >= 0x010000 && Value <= 0xff0000) ||
1040 (Value >= 0x01000000 && Value <= 0xff000000);
1041 }
1042
1043 bool isNEONi32vmov() const {
1044 if (Kind != k_Immediate)
1045 return false;
1046 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1047 // Must be a constant.
1048 if (!CE) return false;
1049 int64_t Value = CE->getValue();
1050 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1051 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1052 return (Value >= 0 && Value < 256) ||
1053 (Value >= 0x0100 && Value <= 0xff00) ||
1054 (Value >= 0x010000 && Value <= 0xff0000) ||
1055 (Value >= 0x01000000 && Value <= 0xff000000) ||
1056 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1057 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1058 }
1059
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001060 bool isNEONi64splat() const {
1061 if (Kind != k_Immediate)
1062 return false;
1063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1064 // Must be a constant.
1065 if (!CE) return false;
1066 uint64_t Value = CE->getValue();
1067 // i64 value with each byte being either 0 or 0xff.
1068 for (unsigned i = 0; i < 8; ++i)
1069 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1070 return true;
1071 }
1072
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001073 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001074 // Add as immediates when possible. Null MCExpr = 0.
1075 if (Expr == 0)
1076 Inst.addOperand(MCOperand::CreateImm(0));
1077 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001078 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1079 else
1080 Inst.addOperand(MCOperand::CreateExpr(Expr));
1081 }
1082
Daniel Dunbar8462b302010-08-11 06:36:53 +00001083 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001084 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001085 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001086 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1087 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001088 }
1089
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001090 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
1092 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1093 }
1094
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001095 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1098 }
1099
1100 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1103 }
1104
Jim Grosbach89df9962011-08-26 21:43:41 +00001105 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1106 assert(N == 1 && "Invalid number of operands!");
1107 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1108 }
1109
1110 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1111 assert(N == 1 && "Invalid number of operands!");
1112 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1113 }
1114
Jim Grosbachd67641b2010-12-06 18:21:12 +00001115 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
1117 Inst.addOperand(MCOperand::CreateReg(getReg()));
1118 }
1119
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001120 void addRegOperands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 Inst.addOperand(MCOperand::CreateReg(getReg()));
1123 }
1124
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001125 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001126 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001127 assert(isRegShiftedReg() &&
1128 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001129 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1130 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001131 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001132 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001133 }
1134
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001135 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001136 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001137 assert(isRegShiftedImm() &&
1138 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001139 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001140 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001141 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001142 }
1143
Jim Grosbach580f4a92011-07-25 22:20:28 +00001144 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001145 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001146 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1147 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001148 }
1149
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001150 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001151 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001152 const SmallVectorImpl<unsigned> &RegList = getRegList();
1153 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001154 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1155 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001156 }
1157
Bill Wendling0f630752010-11-17 04:32:08 +00001158 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1159 addRegListOperands(Inst, N);
1160 }
1161
1162 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1163 addRegListOperands(Inst, N);
1164 }
1165
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001166 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1167 assert(N == 1 && "Invalid number of operands!");
1168 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1169 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1170 }
1171
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001172 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
1174 // Munge the lsb/width into a bitfield mask.
1175 unsigned lsb = Bitfield.LSB;
1176 unsigned width = Bitfield.Width;
1177 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1178 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1179 (32 - (lsb + width)));
1180 Inst.addOperand(MCOperand::CreateImm(Mask));
1181 }
1182
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001183 void addImmOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 1 && "Invalid number of operands!");
1185 addExpr(Inst, getImm());
1186 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001187
Jim Grosbach9d390362011-10-03 23:38:36 +00001188 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
1190 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1191 }
1192
Jim Grosbacha77295d2011-09-08 22:07:06 +00001193 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1194 assert(N == 1 && "Invalid number of operands!");
1195 // FIXME: We really want to scale the value here, but the LDRD/STRD
1196 // instruction don't encode operands that way yet.
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1199 }
1200
Jim Grosbach72f39f82011-08-24 21:22:15 +00001201 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203 // The immediate is scaled by four in the encoding and is stored
1204 // in the MCInst as such. Lop off the low two bits here.
1205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1206 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1207 }
1208
1209 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
1211 // The immediate is scaled by four in the encoding and is stored
1212 // in the MCInst as such. Lop off the low two bits here.
1213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1214 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1215 }
1216
Jim Grosbachf4943352011-07-25 23:09:14 +00001217 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 // The constant encodes as the immediate-1, and we store in the instruction
1220 // the bits as encoded, so subtract off one here.
1221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1222 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1223 }
1224
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001225 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 // The constant encodes as the immediate-1, and we store in the instruction
1228 // the bits as encoded, so subtract off one here.
1229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1230 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1231 }
1232
Jim Grosbach70939ee2011-08-17 21:51:27 +00001233 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 // The constant encodes as the immediate, except for 32, which encodes as
1236 // zero.
1237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1238 unsigned Imm = CE->getValue();
1239 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1240 }
1241
Jim Grosbachf6c05252011-07-21 17:23:04 +00001242 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
1244 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1245 // the instruction as well.
1246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1247 int Val = CE->getValue();
1248 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1249 }
1250
Jim Grosbach89a63372011-10-28 22:36:30 +00001251 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 // The operand is actually a t2_so_imm, but we have its bitwise
1254 // negation in the assembly source, so twiddle it here.
1255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1256 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1257 }
1258
Jim Grosbache70ec842011-10-28 22:50:54 +00001259 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 // The operand is actually a so_imm, but we have its bitwise
1262 // negation in the assembly source, so twiddle it here.
1263 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1264 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1265 }
1266
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001267 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
1269 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1270 }
1271
Jim Grosbach7ce05792011-08-03 23:50:40 +00001272 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001274 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001275 }
1276
Jim Grosbach57dcb852011-10-11 17:29:55 +00001277 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1278 assert(N == 2 && "Invalid number of operands!");
1279 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1280 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1281 }
1282
Jim Grosbach7ce05792011-08-03 23:50:40 +00001283 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001285 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1286 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001287 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1288 // Special case for #-0
1289 if (Val == INT32_MIN) Val = 0;
1290 if (Val < 0) Val = -Val;
1291 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1292 } else {
1293 // For register offset, we encode the shift type and negation flag
1294 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001295 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1296 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001297 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001298 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1299 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001300 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001301 }
1302
Jim Grosbach039c2e12011-08-04 23:01:30 +00001303 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1304 assert(N == 2 && "Invalid number of operands!");
1305 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1306 assert(CE && "non-constant AM2OffsetImm operand!");
1307 int32_t Val = CE->getValue();
1308 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1309 // Special case for #-0
1310 if (Val == INT32_MIN) Val = 0;
1311 if (Val < 0) Val = -Val;
1312 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1313 Inst.addOperand(MCOperand::CreateReg(0));
1314 Inst.addOperand(MCOperand::CreateImm(Val));
1315 }
1316
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001317 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1318 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001319 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1320 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001321 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1322 // Special case for #-0
1323 if (Val == INT32_MIN) Val = 0;
1324 if (Val < 0) Val = -Val;
1325 Val = ARM_AM::getAM3Opc(AddSub, Val);
1326 } else {
1327 // For register offset, we encode the shift type and negation flag
1328 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001329 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001330 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001331 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1332 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001333 Inst.addOperand(MCOperand::CreateImm(Val));
1334 }
1335
1336 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1337 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001338 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001339 int32_t Val =
1340 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1341 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1342 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001343 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001344 }
1345
1346 // Constant offset.
1347 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1348 int32_t Val = CE->getValue();
1349 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1350 // Special case for #-0
1351 if (Val == INT32_MIN) Val = 0;
1352 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001353 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001354 Inst.addOperand(MCOperand::CreateReg(0));
1355 Inst.addOperand(MCOperand::CreateImm(Val));
1356 }
1357
Jim Grosbach7ce05792011-08-03 23:50:40 +00001358 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001360 // If we have an immediate that's not a constant, treat it as a label
1361 // reference needing a fixup. If it is a constant, it's something else
1362 // and we reject it.
1363 if (isImm()) {
1364 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1365 Inst.addOperand(MCOperand::CreateImm(0));
1366 return;
1367 }
1368
Jim Grosbach7ce05792011-08-03 23:50:40 +00001369 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001370 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001371 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1372 // Special case for #-0
1373 if (Val == INT32_MIN) Val = 0;
1374 if (Val < 0) Val = -Val;
1375 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001376 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001377 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001378 }
1379
Jim Grosbacha77295d2011-09-08 22:07:06 +00001380 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001382 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1383 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001384 Inst.addOperand(MCOperand::CreateImm(Val));
1385 }
1386
Jim Grosbachb6aed502011-09-09 18:37:27 +00001387 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
1389 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001390 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1391 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001392 Inst.addOperand(MCOperand::CreateImm(Val));
1393 }
1394
Jim Grosbach7ce05792011-08-03 23:50:40 +00001395 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001397 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1398 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001399 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001400 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001401
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001402 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1403 addMemImm8OffsetOperands(Inst, N);
1404 }
1405
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001406 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001407 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001408 }
1409
1410 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1411 assert(N == 2 && "Invalid number of operands!");
1412 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001413 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001414 addExpr(Inst, getImm());
1415 Inst.addOperand(MCOperand::CreateImm(0));
1416 return;
1417 }
1418
1419 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001420 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001422 Inst.addOperand(MCOperand::CreateImm(Val));
1423 }
1424
Jim Grosbach7ce05792011-08-03 23:50:40 +00001425 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001427 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001428 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001429 addExpr(Inst, getImm());
1430 Inst.addOperand(MCOperand::CreateImm(0));
1431 return;
1432 }
1433
1434 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001435 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1436 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001437 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001438 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001439
Jim Grosbach7f739be2011-09-19 22:21:13 +00001440 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001442 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1443 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001444 }
1445
1446 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001448 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1449 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001450 }
1451
Jim Grosbach7ce05792011-08-03 23:50:40 +00001452 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1453 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001454 unsigned Val =
1455 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1456 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001457 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1458 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001459 Inst.addOperand(MCOperand::CreateImm(Val));
1460 }
1461
Jim Grosbachab899c12011-09-07 23:10:15 +00001462 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001464 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1465 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1466 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001467 }
1468
Jim Grosbach7ce05792011-08-03 23:50:40 +00001469 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001471 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1472 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001473 }
1474
Jim Grosbach60f91a32011-08-19 17:55:24 +00001475 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001477 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1478 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001479 Inst.addOperand(MCOperand::CreateImm(Val));
1480 }
1481
Jim Grosbach38466302011-08-19 18:55:51 +00001482 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1483 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001484 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1485 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001486 Inst.addOperand(MCOperand::CreateImm(Val));
1487 }
1488
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001489 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001491 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1492 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001493 Inst.addOperand(MCOperand::CreateImm(Val));
1494 }
1495
Jim Grosbachecd85892011-08-19 18:13:48 +00001496 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001498 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1499 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001500 Inst.addOperand(MCOperand::CreateImm(Val));
1501 }
1502
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1506 assert(CE && "non-constant post-idx-imm8 operand!");
1507 int Imm = CE->getValue();
1508 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001509 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001510 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1511 Inst.addOperand(MCOperand::CreateImm(Imm));
1512 }
1513
Jim Grosbach2bd01182011-10-11 21:55:36 +00001514 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1517 assert(CE && "non-constant post-idx-imm8s4 operand!");
1518 int Imm = CE->getValue();
1519 bool isAdd = Imm >= 0;
1520 if (Imm == INT32_MIN) Imm = 0;
1521 // Immediate is scaled by 4.
1522 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1523 Inst.addOperand(MCOperand::CreateImm(Imm));
1524 }
1525
Jim Grosbach7ce05792011-08-03 23:50:40 +00001526 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 2 && "Invalid number of operands!");
1528 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001529 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1530 }
1531
1532 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 2 && "Invalid number of operands!");
1534 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1535 // The sign, shift type, and shift amount are encoded in a single operand
1536 // using the AM2 encoding helpers.
1537 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1538 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1539 PostIdxReg.ShiftTy);
1540 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001541 }
1542
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001543 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1546 }
1547
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001548 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1551 }
1552
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001553 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001554 assert(N == 1 && "Invalid number of operands!");
1555 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1556 }
1557
Jim Grosbach7636bf62011-12-02 00:35:16 +00001558 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1559 assert(N == 2 && "Invalid number of operands!");
1560 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1561 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1562 }
1563
Jim Grosbach460a9052011-10-07 23:56:00 +00001564 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1567 }
1568
1569 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1572 }
1573
1574 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
1576 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1577 }
1578
Jim Grosbach0e387b22011-10-17 22:26:03 +00001579 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581 // The immediate encodes the type of constant as well as the value.
1582 // Mask in that this is an i8 splat.
1583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1584 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1585 }
1586
Jim Grosbachea461102011-10-17 23:09:09 +00001587 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 // The immediate encodes the type of constant as well as the value.
1590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1591 unsigned Value = CE->getValue();
1592 if (Value >= 256)
1593 Value = (Value >> 8) | 0xa00;
1594 else
1595 Value |= 0x800;
1596 Inst.addOperand(MCOperand::CreateImm(Value));
1597 }
1598
Jim Grosbach6248a542011-10-18 00:22:00 +00001599 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 // The immediate encodes the type of constant as well as the value.
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 unsigned Value = CE->getValue();
1604 if (Value >= 256 && Value <= 0xff00)
1605 Value = (Value >> 8) | 0x200;
1606 else if (Value > 0xffff && Value <= 0xff0000)
1607 Value = (Value >> 16) | 0x400;
1608 else if (Value > 0xffffff)
1609 Value = (Value >> 24) | 0x600;
1610 Inst.addOperand(MCOperand::CreateImm(Value));
1611 }
1612
1613 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The immediate encodes the type of constant as well as the value.
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 unsigned Value = CE->getValue();
1618 if (Value >= 256 && Value <= 0xffff)
1619 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1620 else if (Value > 0xffff && Value <= 0xffffff)
1621 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1622 else if (Value > 0xffffff)
1623 Value = (Value >> 24) | 0x600;
1624 Inst.addOperand(MCOperand::CreateImm(Value));
1625 }
1626
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001627 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 1 && "Invalid number of operands!");
1629 // The immediate encodes the type of constant as well as the value.
1630 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1631 uint64_t Value = CE->getValue();
1632 unsigned Imm = 0;
1633 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1634 Imm |= (Value & 1) << i;
1635 }
1636 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1637 }
1638
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001639 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001640
Jim Grosbach89df9962011-08-26 21:43:41 +00001641 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001642 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001643 Op->ITMask.Mask = Mask;
1644 Op->StartLoc = S;
1645 Op->EndLoc = S;
1646 return Op;
1647 }
1648
Chris Lattner3a697562010-10-28 17:20:03 +00001649 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001650 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001651 Op->CC.Val = CC;
1652 Op->StartLoc = S;
1653 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001654 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001655 }
1656
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001657 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001658 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001659 Op->Cop.Val = CopVal;
1660 Op->StartLoc = S;
1661 Op->EndLoc = S;
1662 return Op;
1663 }
1664
1665 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001666 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001667 Op->Cop.Val = CopVal;
1668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001673 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1674 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1675 Op->Cop.Val = Val;
1676 Op->StartLoc = S;
1677 Op->EndLoc = E;
1678 return Op;
1679 }
1680
Jim Grosbachd67641b2010-12-06 18:21:12 +00001681 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001682 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001683 Op->Reg.RegNum = RegNum;
1684 Op->StartLoc = S;
1685 Op->EndLoc = S;
1686 return Op;
1687 }
1688
Chris Lattner3a697562010-10-28 17:20:03 +00001689 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001690 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001691 Op->Tok.Data = Str.data();
1692 Op->Tok.Length = Str.size();
1693 Op->StartLoc = S;
1694 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001695 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001696 }
1697
Bill Wendling50d0f582010-11-18 23:43:05 +00001698 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001699 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001700 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001701 Op->StartLoc = S;
1702 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001703 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001704 }
1705
Jim Grosbache8606dc2011-07-13 17:50:29 +00001706 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1707 unsigned SrcReg,
1708 unsigned ShiftReg,
1709 unsigned ShiftImm,
1710 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001711 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001712 Op->RegShiftedReg.ShiftTy = ShTy;
1713 Op->RegShiftedReg.SrcReg = SrcReg;
1714 Op->RegShiftedReg.ShiftReg = ShiftReg;
1715 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001716 Op->StartLoc = S;
1717 Op->EndLoc = E;
1718 return Op;
1719 }
1720
Owen Anderson92a20222011-07-21 18:54:16 +00001721 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1722 unsigned SrcReg,
1723 unsigned ShiftImm,
1724 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001725 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001726 Op->RegShiftedImm.ShiftTy = ShTy;
1727 Op->RegShiftedImm.SrcReg = SrcReg;
1728 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001729 Op->StartLoc = S;
1730 Op->EndLoc = E;
1731 return Op;
1732 }
1733
Jim Grosbach580f4a92011-07-25 22:20:28 +00001734 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001735 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001736 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001737 Op->ShifterImm.isASR = isASR;
1738 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001739 Op->StartLoc = S;
1740 Op->EndLoc = E;
1741 return Op;
1742 }
1743
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001744 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001745 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001746 Op->RotImm.Imm = Imm;
1747 Op->StartLoc = S;
1748 Op->EndLoc = E;
1749 return Op;
1750 }
1751
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001752 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1753 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001755 Op->Bitfield.LSB = LSB;
1756 Op->Bitfield.Width = Width;
1757 Op->StartLoc = S;
1758 Op->EndLoc = E;
1759 return Op;
1760 }
1761
Bill Wendling7729e062010-11-09 22:44:22 +00001762 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001763 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001764 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001765 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001766
Jim Grosbachd300b942011-09-13 22:56:44 +00001767 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001768 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001769 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001770 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001771 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001772
1773 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001774 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001775 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001776 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001777 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001778 Op->StartLoc = StartLoc;
1779 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001780 return Op;
1781 }
1782
Jim Grosbach862019c2011-10-18 23:02:30 +00001783 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1784 SMLoc S, SMLoc E) {
1785 ARMOperand *Op = new ARMOperand(k_VectorList);
1786 Op->VectorList.RegNum = RegNum;
1787 Op->VectorList.Count = Count;
1788 Op->StartLoc = S;
1789 Op->EndLoc = E;
1790 return Op;
1791 }
1792
Jim Grosbach98b05a52011-11-30 01:09:44 +00001793 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1794 SMLoc S, SMLoc E) {
1795 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1796 Op->VectorList.RegNum = RegNum;
1797 Op->VectorList.Count = Count;
1798 Op->StartLoc = S;
1799 Op->EndLoc = E;
1800 return Op;
1801 }
1802
Jim Grosbach7636bf62011-12-02 00:35:16 +00001803 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1804 unsigned Index, SMLoc S, SMLoc E) {
1805 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1806 Op->VectorList.RegNum = RegNum;
1807 Op->VectorList.Count = Count;
1808 Op->VectorList.LaneIndex = Index;
1809 Op->StartLoc = S;
1810 Op->EndLoc = E;
1811 return Op;
1812 }
1813
Jim Grosbach460a9052011-10-07 23:56:00 +00001814 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1815 MCContext &Ctx) {
1816 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1817 Op->VectorIndex.Val = Idx;
1818 Op->StartLoc = S;
1819 Op->EndLoc = E;
1820 return Op;
1821 }
1822
Chris Lattner3a697562010-10-28 17:20:03 +00001823 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001824 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001825 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001826 Op->StartLoc = S;
1827 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001828 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001829 }
1830
Jim Grosbach9d390362011-10-03 23:38:36 +00001831 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001832 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001833 Op->FPImm.Val = Val;
1834 Op->StartLoc = S;
1835 Op->EndLoc = S;
1836 return Op;
1837 }
1838
Jim Grosbach7ce05792011-08-03 23:50:40 +00001839 static ARMOperand *CreateMem(unsigned BaseRegNum,
1840 const MCConstantExpr *OffsetImm,
1841 unsigned OffsetRegNum,
1842 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001843 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001844 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001845 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001846 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001847 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001848 Op->Memory.BaseRegNum = BaseRegNum;
1849 Op->Memory.OffsetImm = OffsetImm;
1850 Op->Memory.OffsetRegNum = OffsetRegNum;
1851 Op->Memory.ShiftType = ShiftType;
1852 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001853 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001854 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001855 Op->StartLoc = S;
1856 Op->EndLoc = E;
1857 return Op;
1858 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001859
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001860 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1861 ARM_AM::ShiftOpc ShiftTy,
1862 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001863 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001864 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001865 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001866 Op->PostIdxReg.isAdd = isAdd;
1867 Op->PostIdxReg.ShiftTy = ShiftTy;
1868 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001869 Op->StartLoc = S;
1870 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001871 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001872 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001873
1874 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001875 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001876 Op->MBOpt.Val = Opt;
1877 Op->StartLoc = S;
1878 Op->EndLoc = S;
1879 return Op;
1880 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001881
1882 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001883 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001884 Op->IFlags.Val = IFlags;
1885 Op->StartLoc = S;
1886 Op->EndLoc = S;
1887 return Op;
1888 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001889
1890 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001892 Op->MMask.Val = MMask;
1893 Op->StartLoc = S;
1894 Op->EndLoc = S;
1895 return Op;
1896 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001897};
1898
1899} // end anonymous namespace.
1900
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001901void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001902 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001903 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001904 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1905 << ") >";
1906 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001908 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001909 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001911 OS << "<ccout " << getReg() << ">";
1912 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001913 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001914 static const char *MaskStr[] = {
1915 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1916 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1917 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001918 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1919 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1920 break;
1921 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001922 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001923 OS << "<coprocessor number: " << getCoproc() << ">";
1924 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001925 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001926 OS << "<coprocessor register: " << getCoproc() << ">";
1927 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001928 case k_CoprocOption:
1929 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1930 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001932 OS << "<mask: " << getMSRMask() << ">";
1933 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001934 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001935 getImm()->print(OS);
1936 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001937 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001938 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1939 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001941 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001942 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001943 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001944 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001945 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001946 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1947 << PostIdxReg.RegNum;
1948 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1949 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1950 << PostIdxReg.ShiftImm;
1951 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001952 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001953 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001954 OS << "<ARM_PROC::";
1955 unsigned IFlags = getProcIFlags();
1956 for (int i=2; i >= 0; --i)
1957 if (IFlags & (1 << i))
1958 OS << ARM_PROC::IFlagsToString(1 << i);
1959 OS << ">";
1960 break;
1961 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001963 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001964 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001965 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001966 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1967 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001968 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001970 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001971 << RegShiftedReg.SrcReg << " "
1972 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1973 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001974 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001975 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001976 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001977 << RegShiftedImm.SrcReg << " "
1978 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1979 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00001980 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001981 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001982 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1983 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001984 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001985 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1986 << ", width: " << Bitfield.Width << ">";
1987 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 case k_RegisterList:
1989 case k_DPRRegisterList:
1990 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001991 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001992
Bill Wendling5fa22a12010-11-09 23:28:44 +00001993 const SmallVectorImpl<unsigned> &RegList = getRegList();
1994 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001995 I = RegList.begin(), E = RegList.end(); I != E; ) {
1996 OS << *I;
1997 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001998 }
1999
2000 OS << ">";
2001 break;
2002 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002003 case k_VectorList:
2004 OS << "<vector_list " << VectorList.Count << " * "
2005 << VectorList.RegNum << ">";
2006 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002007 case k_VectorListAllLanes:
2008 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2009 << VectorList.RegNum << ">";
2010 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002011 case k_VectorListIndexed:
2012 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2013 << VectorList.Count << " * " << VectorList.RegNum << ">";
2014 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002015 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002016 OS << "'" << getToken() << "'";
2017 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002018 case k_VectorIndex:
2019 OS << "<vectorindex " << getVectorIndex() << ">";
2020 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002021 }
2022}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002023
2024/// @name Auto-generated Match Functions
2025/// {
2026
2027static unsigned MatchRegisterName(StringRef Name);
2028
2029/// }
2030
Bob Wilson69df7232011-02-03 21:46:10 +00002031bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2032 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002033 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002034
2035 return (RegNo == (unsigned)-1);
2036}
2037
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002038/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002039/// and if it is a register name the token is eaten and the register number is
2040/// returned. Otherwise return -1.
2041///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002042int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002043 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002044 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002045
Chris Lattnere5658fa2010-10-30 04:09:10 +00002046 // FIXME: Validate register for the current architecture; we have to do
2047 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002048 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002049 unsigned RegNum = MatchRegisterName(lowerCase);
2050 if (!RegNum) {
2051 RegNum = StringSwitch<unsigned>(lowerCase)
2052 .Case("r13", ARM::SP)
2053 .Case("r14", ARM::LR)
2054 .Case("r15", ARM::PC)
2055 .Case("ip", ARM::R12)
2056 .Default(0);
2057 }
2058 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002059
Chris Lattnere5658fa2010-10-30 04:09:10 +00002060 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002061
Chris Lattnere5658fa2010-10-30 04:09:10 +00002062 return RegNum;
2063}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002064
Jim Grosbach19906722011-07-13 18:49:30 +00002065// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2066// If a recoverable error occurs, return 1. If an irrecoverable error
2067// occurs, return -1. An irrecoverable error is one where tokens have been
2068// consumed in the process of trying to parse the shifter (i.e., when it is
2069// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002070int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002071 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2072 SMLoc S = Parser.getTok().getLoc();
2073 const AsmToken &Tok = Parser.getTok();
2074 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2075
Benjamin Kramer59085362011-11-06 20:37:06 +00002076 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002077 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2078 .Case("lsl", ARM_AM::lsl)
2079 .Case("lsr", ARM_AM::lsr)
2080 .Case("asr", ARM_AM::asr)
2081 .Case("ror", ARM_AM::ror)
2082 .Case("rrx", ARM_AM::rrx)
2083 .Default(ARM_AM::no_shift);
2084
2085 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002086 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002087
Jim Grosbache8606dc2011-07-13 17:50:29 +00002088 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002089
Jim Grosbache8606dc2011-07-13 17:50:29 +00002090 // The source register for the shift has already been added to the
2091 // operand list, so we need to pop it off and combine it into the shifted
2092 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002093 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002094 if (!PrevOp->isReg())
2095 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2096 int SrcReg = PrevOp->getReg();
2097 int64_t Imm = 0;
2098 int ShiftReg = 0;
2099 if (ShiftTy == ARM_AM::rrx) {
2100 // RRX Doesn't have an explicit shift amount. The encoder expects
2101 // the shift register to be the same as the source register. Seems odd,
2102 // but OK.
2103 ShiftReg = SrcReg;
2104 } else {
2105 // Figure out if this is shifted by a constant or a register (for non-RRX).
2106 if (Parser.getTok().is(AsmToken::Hash)) {
2107 Parser.Lex(); // Eat hash.
2108 SMLoc ImmLoc = Parser.getTok().getLoc();
2109 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002110 if (getParser().ParseExpression(ShiftExpr)) {
2111 Error(ImmLoc, "invalid immediate shift value");
2112 return -1;
2113 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002114 // The expression must be evaluatable as an immediate.
2115 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002116 if (!CE) {
2117 Error(ImmLoc, "invalid immediate shift value");
2118 return -1;
2119 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002120 // Range check the immediate.
2121 // lsl, ror: 0 <= imm <= 31
2122 // lsr, asr: 0 <= imm <= 32
2123 Imm = CE->getValue();
2124 if (Imm < 0 ||
2125 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2126 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002127 Error(ImmLoc, "immediate shift value out of range");
2128 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002129 }
2130 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002131 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002132 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002133 if (ShiftReg == -1) {
2134 Error (L, "expected immediate or register in shift operand");
2135 return -1;
2136 }
2137 } else {
2138 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002139 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002140 return -1;
2141 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002142 }
2143
Owen Anderson92a20222011-07-21 18:54:16 +00002144 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2145 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002146 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002147 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002148 else
2149 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2150 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002151
Jim Grosbach19906722011-07-13 18:49:30 +00002152 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002153}
2154
2155
Bill Wendling50d0f582010-11-18 23:43:05 +00002156/// Try to parse a register name. The token must be an Identifier when called.
2157/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2158/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002159///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002160/// TODO this is likely to change to allow different register types and or to
2161/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002162bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002163tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002164 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002165 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002166 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002167 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002168
Bill Wendling50d0f582010-11-18 23:43:05 +00002169 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002170
Chris Lattnere5658fa2010-10-30 04:09:10 +00002171 const AsmToken &ExclaimTok = Parser.getTok();
2172 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002173 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2174 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002175 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002176 return false;
2177 }
2178
2179 // Also check for an index operand. This is only legal for vector registers,
2180 // but that'll get caught OK in operand matching, so we don't need to
2181 // explicitly filter everything else out here.
2182 if (Parser.getTok().is(AsmToken::LBrac)) {
2183 SMLoc SIdx = Parser.getTok().getLoc();
2184 Parser.Lex(); // Eat left bracket token.
2185
2186 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002187 if (getParser().ParseExpression(ImmVal))
2188 return MatchOperand_ParseFail;
2189 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2190 if (!MCE) {
2191 TokError("immediate value expected for vector index");
2192 return MatchOperand_ParseFail;
2193 }
2194
2195 SMLoc E = Parser.getTok().getLoc();
2196 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2197 Error(E, "']' expected");
2198 return MatchOperand_ParseFail;
2199 }
2200
2201 Parser.Lex(); // Eat right bracket token.
2202
2203 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2204 SIdx, E,
2205 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002206 }
2207
Bill Wendling50d0f582010-11-18 23:43:05 +00002208 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002209}
2210
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002211/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2212/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2213/// "c5", ...
2214static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002215 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2216 // but efficient.
2217 switch (Name.size()) {
2218 default: break;
2219 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002220 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002221 return -1;
2222 switch (Name[1]) {
2223 default: return -1;
2224 case '0': return 0;
2225 case '1': return 1;
2226 case '2': return 2;
2227 case '3': return 3;
2228 case '4': return 4;
2229 case '5': return 5;
2230 case '6': return 6;
2231 case '7': return 7;
2232 case '8': return 8;
2233 case '9': return 9;
2234 }
2235 break;
2236 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002237 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002238 return -1;
2239 switch (Name[2]) {
2240 default: return -1;
2241 case '0': return 10;
2242 case '1': return 11;
2243 case '2': return 12;
2244 case '3': return 13;
2245 case '4': return 14;
2246 case '5': return 15;
2247 }
2248 break;
2249 }
2250
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002251 return -1;
2252}
2253
Jim Grosbach89df9962011-08-26 21:43:41 +00002254/// parseITCondCode - Try to parse a condition code for an IT instruction.
2255ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2256parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2257 SMLoc S = Parser.getTok().getLoc();
2258 const AsmToken &Tok = Parser.getTok();
2259 if (!Tok.is(AsmToken::Identifier))
2260 return MatchOperand_NoMatch;
2261 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2262 .Case("eq", ARMCC::EQ)
2263 .Case("ne", ARMCC::NE)
2264 .Case("hs", ARMCC::HS)
2265 .Case("cs", ARMCC::HS)
2266 .Case("lo", ARMCC::LO)
2267 .Case("cc", ARMCC::LO)
2268 .Case("mi", ARMCC::MI)
2269 .Case("pl", ARMCC::PL)
2270 .Case("vs", ARMCC::VS)
2271 .Case("vc", ARMCC::VC)
2272 .Case("hi", ARMCC::HI)
2273 .Case("ls", ARMCC::LS)
2274 .Case("ge", ARMCC::GE)
2275 .Case("lt", ARMCC::LT)
2276 .Case("gt", ARMCC::GT)
2277 .Case("le", ARMCC::LE)
2278 .Case("al", ARMCC::AL)
2279 .Default(~0U);
2280 if (CC == ~0U)
2281 return MatchOperand_NoMatch;
2282 Parser.Lex(); // Eat the token.
2283
2284 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2285
2286 return MatchOperand_Success;
2287}
2288
Jim Grosbach43904292011-07-25 20:14:50 +00002289/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002290/// token must be an Identifier when called, and if it is a coprocessor
2291/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002292ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002293parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002294 SMLoc S = Parser.getTok().getLoc();
2295 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002296 if (Tok.isNot(AsmToken::Identifier))
2297 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002298
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002299 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002300 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002301 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002302
2303 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002304 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002305 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002306}
2307
Jim Grosbach43904292011-07-25 20:14:50 +00002308/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002309/// token must be an Identifier when called, and if it is a coprocessor
2310/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002311ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002312parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002313 SMLoc S = Parser.getTok().getLoc();
2314 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002315 if (Tok.isNot(AsmToken::Identifier))
2316 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002317
2318 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2319 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002320 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002321
2322 Parser.Lex(); // Eat identifier token.
2323 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002324 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002325}
2326
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002327/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2328/// coproc_option : '{' imm0_255 '}'
2329ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2330parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2331 SMLoc S = Parser.getTok().getLoc();
2332
2333 // If this isn't a '{', this isn't a coprocessor immediate operand.
2334 if (Parser.getTok().isNot(AsmToken::LCurly))
2335 return MatchOperand_NoMatch;
2336 Parser.Lex(); // Eat the '{'
2337
2338 const MCExpr *Expr;
2339 SMLoc Loc = Parser.getTok().getLoc();
2340 if (getParser().ParseExpression(Expr)) {
2341 Error(Loc, "illegal expression");
2342 return MatchOperand_ParseFail;
2343 }
2344 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2345 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2346 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2347 return MatchOperand_ParseFail;
2348 }
2349 int Val = CE->getValue();
2350
2351 // Check for and consume the closing '}'
2352 if (Parser.getTok().isNot(AsmToken::RCurly))
2353 return MatchOperand_ParseFail;
2354 SMLoc E = Parser.getTok().getLoc();
2355 Parser.Lex(); // Eat the '}'
2356
2357 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2358 return MatchOperand_Success;
2359}
2360
Jim Grosbachd0588e22011-09-14 18:08:35 +00002361// For register list parsing, we need to map from raw GPR register numbering
2362// to the enumeration values. The enumeration values aren't sorted by
2363// register number due to our using "sp", "lr" and "pc" as canonical names.
2364static unsigned getNextRegister(unsigned Reg) {
2365 // If this is a GPR, we need to do it manually, otherwise we can rely
2366 // on the sort ordering of the enumeration since the other reg-classes
2367 // are sane.
2368 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2369 return Reg + 1;
2370 switch(Reg) {
2371 default: assert(0 && "Invalid GPR number!");
2372 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2373 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2374 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2375 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2376 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2377 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2378 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2379 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2380 }
2381}
2382
Jim Grosbachce485e72011-11-11 21:27:40 +00002383// Return the low-subreg of a given Q register.
2384static unsigned getDRegFromQReg(unsigned QReg) {
2385 switch (QReg) {
2386 default: llvm_unreachable("expected a Q register!");
2387 case ARM::Q0: return ARM::D0;
2388 case ARM::Q1: return ARM::D2;
2389 case ARM::Q2: return ARM::D4;
2390 case ARM::Q3: return ARM::D6;
2391 case ARM::Q4: return ARM::D8;
2392 case ARM::Q5: return ARM::D10;
2393 case ARM::Q6: return ARM::D12;
2394 case ARM::Q7: return ARM::D14;
2395 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002396 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002397 case ARM::Q10: return ARM::D20;
2398 case ARM::Q11: return ARM::D22;
2399 case ARM::Q12: return ARM::D24;
2400 case ARM::Q13: return ARM::D26;
2401 case ARM::Q14: return ARM::D28;
2402 case ARM::Q15: return ARM::D30;
2403 }
2404}
2405
Jim Grosbachd0588e22011-09-14 18:08:35 +00002406/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002407bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002408parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002409 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002410 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002411 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002412 Parser.Lex(); // Eat '{' token.
2413 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002414
Jim Grosbachd0588e22011-09-14 18:08:35 +00002415 // Check the first register in the list to see what register class
2416 // this is a list of.
2417 int Reg = tryParseRegister();
2418 if (Reg == -1)
2419 return Error(RegLoc, "register expected");
2420
Jim Grosbachce485e72011-11-11 21:27:40 +00002421 // The reglist instructions have at most 16 registers, so reserve
2422 // space for that many.
2423 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2424
2425 // Allow Q regs and just interpret them as the two D sub-registers.
2426 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2427 Reg = getDRegFromQReg(Reg);
2428 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2429 ++Reg;
2430 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002431 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002432 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2433 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2434 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2435 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2436 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2437 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2438 else
2439 return Error(RegLoc, "invalid register in register list");
2440
Jim Grosbachce485e72011-11-11 21:27:40 +00002441 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002442 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002443
Jim Grosbachd0588e22011-09-14 18:08:35 +00002444 // This starts immediately after the first register token in the list,
2445 // so we can see either a comma or a minus (range separator) as a legal
2446 // next token.
2447 while (Parser.getTok().is(AsmToken::Comma) ||
2448 Parser.getTok().is(AsmToken::Minus)) {
2449 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002450 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002451 SMLoc EndLoc = Parser.getTok().getLoc();
2452 int EndReg = tryParseRegister();
2453 if (EndReg == -1)
2454 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002455 // Allow Q regs and just interpret them as the two D sub-registers.
2456 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2457 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002458 // If the register is the same as the start reg, there's nothing
2459 // more to do.
2460 if (Reg == EndReg)
2461 continue;
2462 // The register must be in the same register class as the first.
2463 if (!RC->contains(EndReg))
2464 return Error(EndLoc, "invalid register in register list");
2465 // Ranges must go from low to high.
2466 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2467 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002468
Jim Grosbachd0588e22011-09-14 18:08:35 +00002469 // Add all the registers in the range to the register list.
2470 while (Reg != EndReg) {
2471 Reg = getNextRegister(Reg);
2472 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2473 }
2474 continue;
2475 }
2476 Parser.Lex(); // Eat the comma.
2477 RegLoc = Parser.getTok().getLoc();
2478 int OldReg = Reg;
2479 Reg = tryParseRegister();
2480 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002481 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002482 // Allow Q regs and just interpret them as the two D sub-registers.
2483 bool isQReg = false;
2484 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2485 Reg = getDRegFromQReg(Reg);
2486 isQReg = true;
2487 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002488 // The register must be in the same register class as the first.
2489 if (!RC->contains(Reg))
2490 return Error(RegLoc, "invalid register in register list");
2491 // List must be monotonically increasing.
2492 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2493 return Error(RegLoc, "register list not in ascending order");
2494 // VFP register lists must also be contiguous.
2495 // It's OK to use the enumeration values directly here rather, as the
2496 // VFP register classes have the enum sorted properly.
2497 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2498 Reg != OldReg + 1)
2499 return Error(RegLoc, "non-contiguous register range");
2500 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002501 if (isQReg)
2502 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002503 }
2504
Jim Grosbachd0588e22011-09-14 18:08:35 +00002505 SMLoc E = Parser.getTok().getLoc();
2506 if (Parser.getTok().isNot(AsmToken::RCurly))
2507 return Error(E, "'}' expected");
2508 Parser.Lex(); // Eat '}' token.
2509
Bill Wendling50d0f582010-11-18 23:43:05 +00002510 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2511 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002512}
2513
Jim Grosbach98b05a52011-11-30 01:09:44 +00002514// Helper function to parse the lane index for vector lists.
2515ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002516parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2517 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002518 if (Parser.getTok().is(AsmToken::LBrac)) {
2519 Parser.Lex(); // Eat the '['.
2520 if (Parser.getTok().is(AsmToken::RBrac)) {
2521 // "Dn[]" is the 'all lanes' syntax.
2522 LaneKind = AllLanes;
2523 Parser.Lex(); // Eat the ']'.
2524 return MatchOperand_Success;
2525 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002526 if (Parser.getTok().is(AsmToken::Integer)) {
2527 int64_t Val = Parser.getTok().getIntVal();
2528 // Make this range check context sensitive for .8, .16, .32.
2529 if (Val < 0 && Val > 7)
2530 Error(Parser.getTok().getLoc(), "lane index out of range");
2531 Index = Val;
2532 LaneKind = IndexedLane;
2533 Parser.Lex(); // Eat the token;
2534 if (Parser.getTok().isNot(AsmToken::RBrac))
2535 Error(Parser.getTok().getLoc(), "']' expected");
2536 Parser.Lex(); // Eat the ']'.
2537 return MatchOperand_Success;
2538 }
2539 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002540 return MatchOperand_ParseFail;
2541 }
2542 LaneKind = NoLanes;
2543 return MatchOperand_Success;
2544}
2545
Jim Grosbach862019c2011-10-18 23:02:30 +00002546// parse a vector register list
2547ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2548parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002549 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002550 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002551 SMLoc S = Parser.getTok().getLoc();
2552 // As an extension (to match gas), support a plain D register or Q register
2553 // (without encosing curly braces) as a single or double entry list,
2554 // respectively.
2555 if (Parser.getTok().is(AsmToken::Identifier)) {
2556 int Reg = tryParseRegister();
2557 if (Reg == -1)
2558 return MatchOperand_NoMatch;
2559 SMLoc E = Parser.getTok().getLoc();
2560 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002561 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002562 if (Res != MatchOperand_Success)
2563 return Res;
2564 switch (LaneKind) {
2565 default:
2566 assert(0 && "unexpected lane kind!");
2567 case NoLanes:
2568 E = Parser.getTok().getLoc();
2569 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2570 break;
2571 case AllLanes:
2572 E = Parser.getTok().getLoc();
2573 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2574 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002575 case IndexedLane:
2576 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2577 LaneIndex, S,E));
2578 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002579 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002580 return MatchOperand_Success;
2581 }
2582 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2583 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002584 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002585 if (Res != MatchOperand_Success)
2586 return Res;
2587 switch (LaneKind) {
2588 default:
2589 assert(0 && "unexpected lane kind!");
2590 case NoLanes:
2591 E = Parser.getTok().getLoc();
2592 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2593 break;
2594 case AllLanes:
2595 E = Parser.getTok().getLoc();
2596 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2597 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002598 case IndexedLane:
2599 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2600 LaneIndex, S,E));
2601 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002602 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002603 return MatchOperand_Success;
2604 }
2605 Error(S, "vector register expected");
2606 return MatchOperand_ParseFail;
2607 }
2608
2609 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002610 return MatchOperand_NoMatch;
2611
Jim Grosbach862019c2011-10-18 23:02:30 +00002612 Parser.Lex(); // Eat '{' token.
2613 SMLoc RegLoc = Parser.getTok().getLoc();
2614
2615 int Reg = tryParseRegister();
2616 if (Reg == -1) {
2617 Error(RegLoc, "register expected");
2618 return MatchOperand_ParseFail;
2619 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002620 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002621 unsigned FirstReg = Reg;
2622 // The list is of D registers, but we also allow Q regs and just interpret
2623 // them as the two D sub-registers.
2624 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2625 FirstReg = Reg = getDRegFromQReg(Reg);
2626 ++Reg;
2627 ++Count;
2628 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002629 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002630 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002631
Jim Grosbache43862b2011-11-15 23:19:15 +00002632 while (Parser.getTok().is(AsmToken::Comma) ||
2633 Parser.getTok().is(AsmToken::Minus)) {
2634 if (Parser.getTok().is(AsmToken::Minus)) {
2635 Parser.Lex(); // Eat the minus.
2636 SMLoc EndLoc = Parser.getTok().getLoc();
2637 int EndReg = tryParseRegister();
2638 if (EndReg == -1) {
2639 Error(EndLoc, "register expected");
2640 return MatchOperand_ParseFail;
2641 }
2642 // Allow Q regs and just interpret them as the two D sub-registers.
2643 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2644 EndReg = getDRegFromQReg(EndReg) + 1;
2645 // If the register is the same as the start reg, there's nothing
2646 // more to do.
2647 if (Reg == EndReg)
2648 continue;
2649 // The register must be in the same register class as the first.
2650 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2651 Error(EndLoc, "invalid register in register list");
2652 return MatchOperand_ParseFail;
2653 }
2654 // Ranges must go from low to high.
2655 if (Reg > EndReg) {
2656 Error(EndLoc, "bad range in register list");
2657 return MatchOperand_ParseFail;
2658 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002659 // Parse the lane specifier if present.
2660 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002661 unsigned NextLaneIndex;
2662 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002663 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002664 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002665 Error(EndLoc, "mismatched lane index in register list");
2666 return MatchOperand_ParseFail;
2667 }
2668 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002669
2670 // Add all the registers in the range to the register list.
2671 Count += EndReg - Reg;
2672 Reg = EndReg;
2673 continue;
2674 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002675 Parser.Lex(); // Eat the comma.
2676 RegLoc = Parser.getTok().getLoc();
2677 int OldReg = Reg;
2678 Reg = tryParseRegister();
2679 if (Reg == -1) {
2680 Error(RegLoc, "register expected");
2681 return MatchOperand_ParseFail;
2682 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002683 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002684 // It's OK to use the enumeration values directly here rather, as the
2685 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002686 //
2687 // The list is of D registers, but we also allow Q regs and just interpret
2688 // them as the two D sub-registers.
2689 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2690 Reg = getDRegFromQReg(Reg);
2691 if (Reg != OldReg + 1) {
2692 Error(RegLoc, "non-contiguous register range");
2693 return MatchOperand_ParseFail;
2694 }
2695 ++Reg;
2696 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002697 // Parse the lane specifier if present.
2698 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002699 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002700 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002701 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002702 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002703 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002704 Error(EndLoc, "mismatched lane index in register list");
2705 return MatchOperand_ParseFail;
2706 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002707 continue;
2708 }
2709 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002710 if (Reg != OldReg + 1) {
2711 Error(RegLoc, "non-contiguous register range");
2712 return MatchOperand_ParseFail;
2713 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002714 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002715 // Parse the lane specifier if present.
2716 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002717 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002718 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002719 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002720 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002721 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002722 Error(EndLoc, "mismatched lane index in register list");
2723 return MatchOperand_ParseFail;
2724 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002725 }
2726
2727 SMLoc E = Parser.getTok().getLoc();
2728 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2729 Error(E, "'}' expected");
2730 return MatchOperand_ParseFail;
2731 }
2732 Parser.Lex(); // Eat '}' token.
2733
Jim Grosbach98b05a52011-11-30 01:09:44 +00002734 switch (LaneKind) {
2735 default:
2736 assert(0 && "unexpected lane kind in register list.");
2737 case NoLanes:
2738 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2739 break;
2740 case AllLanes:
2741 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2742 S, E));
2743 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002744 case IndexedLane:
2745 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2746 LaneIndex, S, E));
2747 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002748 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002749 return MatchOperand_Success;
2750}
2751
Jim Grosbach43904292011-07-25 20:14:50 +00002752/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002753ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002754parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002755 SMLoc S = Parser.getTok().getLoc();
2756 const AsmToken &Tok = Parser.getTok();
2757 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2758 StringRef OptStr = Tok.getString();
2759
2760 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2761 .Case("sy", ARM_MB::SY)
2762 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002763 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002764 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002765 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002766 .Case("ishst", ARM_MB::ISHST)
2767 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002768 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002769 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002770 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002771 .Case("osh", ARM_MB::OSH)
2772 .Case("oshst", ARM_MB::OSHST)
2773 .Default(~0U);
2774
2775 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002776 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002777
2778 Parser.Lex(); // Eat identifier token.
2779 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002780 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002781}
2782
Jim Grosbach43904292011-07-25 20:14:50 +00002783/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002784ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002785parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002786 SMLoc S = Parser.getTok().getLoc();
2787 const AsmToken &Tok = Parser.getTok();
2788 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2789 StringRef IFlagsStr = Tok.getString();
2790
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002791 // An iflags string of "none" is interpreted to mean that none of the AIF
2792 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002793 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002794 if (IFlagsStr != "none") {
2795 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2796 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2797 .Case("a", ARM_PROC::A)
2798 .Case("i", ARM_PROC::I)
2799 .Case("f", ARM_PROC::F)
2800 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002801
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002802 // If some specific iflag is already set, it means that some letter is
2803 // present more than once, this is not acceptable.
2804 if (Flag == ~0U || (IFlags & Flag))
2805 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002806
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002807 IFlags |= Flag;
2808 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002809 }
2810
2811 Parser.Lex(); // Eat identifier token.
2812 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2813 return MatchOperand_Success;
2814}
2815
Jim Grosbach43904292011-07-25 20:14:50 +00002816/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002817ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002818parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002819 SMLoc S = Parser.getTok().getLoc();
2820 const AsmToken &Tok = Parser.getTok();
2821 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2822 StringRef Mask = Tok.getString();
2823
James Molloyacad68d2011-09-28 14:21:38 +00002824 if (isMClass()) {
2825 // See ARMv6-M 10.1.1
2826 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2827 .Case("apsr", 0)
2828 .Case("iapsr", 1)
2829 .Case("eapsr", 2)
2830 .Case("xpsr", 3)
2831 .Case("ipsr", 5)
2832 .Case("epsr", 6)
2833 .Case("iepsr", 7)
2834 .Case("msp", 8)
2835 .Case("psp", 9)
2836 .Case("primask", 16)
2837 .Case("basepri", 17)
2838 .Case("basepri_max", 18)
2839 .Case("faultmask", 19)
2840 .Case("control", 20)
2841 .Default(~0U);
2842
2843 if (FlagsVal == ~0U)
2844 return MatchOperand_NoMatch;
2845
2846 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2847 // basepri, basepri_max and faultmask only valid for V7m.
2848 return MatchOperand_NoMatch;
2849
2850 Parser.Lex(); // Eat identifier token.
2851 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2852 return MatchOperand_Success;
2853 }
2854
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002855 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2856 size_t Start = 0, Next = Mask.find('_');
2857 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002858 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002859 if (Next != StringRef::npos)
2860 Flags = Mask.slice(Next+1, Mask.size());
2861
2862 // FlagsVal contains the complete mask:
2863 // 3-0: Mask
2864 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2865 unsigned FlagsVal = 0;
2866
2867 if (SpecReg == "apsr") {
2868 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002869 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002870 .Case("g", 0x4) // same as CPSR_s
2871 .Case("nzcvqg", 0xc) // same as CPSR_fs
2872 .Default(~0U);
2873
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002874 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002875 if (!Flags.empty())
2876 return MatchOperand_NoMatch;
2877 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002878 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002879 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002880 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002881 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2882 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002883 for (int i = 0, e = Flags.size(); i != e; ++i) {
2884 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2885 .Case("c", 1)
2886 .Case("x", 2)
2887 .Case("s", 4)
2888 .Case("f", 8)
2889 .Default(~0U);
2890
2891 // If some specific flag is already set, it means that some letter is
2892 // present more than once, this is not acceptable.
2893 if (FlagsVal == ~0U || (FlagsVal & Flag))
2894 return MatchOperand_NoMatch;
2895 FlagsVal |= Flag;
2896 }
2897 } else // No match for special register.
2898 return MatchOperand_NoMatch;
2899
Owen Anderson7784f1d2011-10-21 18:43:28 +00002900 // Special register without flags is NOT equivalent to "fc" flags.
2901 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2902 // two lines would enable gas compatibility at the expense of breaking
2903 // round-tripping.
2904 //
2905 // if (!FlagsVal)
2906 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002907
2908 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2909 if (SpecReg == "spsr")
2910 FlagsVal |= 16;
2911
2912 Parser.Lex(); // Eat identifier token.
2913 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2914 return MatchOperand_Success;
2915}
2916
Jim Grosbachf6c05252011-07-21 17:23:04 +00002917ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2918parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2919 int Low, int High) {
2920 const AsmToken &Tok = Parser.getTok();
2921 if (Tok.isNot(AsmToken::Identifier)) {
2922 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2923 return MatchOperand_ParseFail;
2924 }
2925 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002926 std::string LowerOp = Op.lower();
2927 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002928 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2929 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2930 return MatchOperand_ParseFail;
2931 }
2932 Parser.Lex(); // Eat shift type token.
2933
2934 // There must be a '#' and a shift amount.
2935 if (Parser.getTok().isNot(AsmToken::Hash)) {
2936 Error(Parser.getTok().getLoc(), "'#' expected");
2937 return MatchOperand_ParseFail;
2938 }
2939 Parser.Lex(); // Eat hash token.
2940
2941 const MCExpr *ShiftAmount;
2942 SMLoc Loc = Parser.getTok().getLoc();
2943 if (getParser().ParseExpression(ShiftAmount)) {
2944 Error(Loc, "illegal expression");
2945 return MatchOperand_ParseFail;
2946 }
2947 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2948 if (!CE) {
2949 Error(Loc, "constant expression expected");
2950 return MatchOperand_ParseFail;
2951 }
2952 int Val = CE->getValue();
2953 if (Val < Low || Val > High) {
2954 Error(Loc, "immediate value out of range");
2955 return MatchOperand_ParseFail;
2956 }
2957
2958 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2959
2960 return MatchOperand_Success;
2961}
2962
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002963ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2964parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2965 const AsmToken &Tok = Parser.getTok();
2966 SMLoc S = Tok.getLoc();
2967 if (Tok.isNot(AsmToken::Identifier)) {
2968 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2969 return MatchOperand_ParseFail;
2970 }
2971 int Val = StringSwitch<int>(Tok.getString())
2972 .Case("be", 1)
2973 .Case("le", 0)
2974 .Default(-1);
2975 Parser.Lex(); // Eat the token.
2976
2977 if (Val == -1) {
2978 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2979 return MatchOperand_ParseFail;
2980 }
2981 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2982 getContext()),
2983 S, Parser.getTok().getLoc()));
2984 return MatchOperand_Success;
2985}
2986
Jim Grosbach580f4a92011-07-25 22:20:28 +00002987/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2988/// instructions. Legal values are:
2989/// lsl #n 'n' in [0,31]
2990/// asr #n 'n' in [1,32]
2991/// n == 32 encoded as n == 0.
2992ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2993parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2994 const AsmToken &Tok = Parser.getTok();
2995 SMLoc S = Tok.getLoc();
2996 if (Tok.isNot(AsmToken::Identifier)) {
2997 Error(S, "shift operator 'asr' or 'lsl' expected");
2998 return MatchOperand_ParseFail;
2999 }
3000 StringRef ShiftName = Tok.getString();
3001 bool isASR;
3002 if (ShiftName == "lsl" || ShiftName == "LSL")
3003 isASR = false;
3004 else if (ShiftName == "asr" || ShiftName == "ASR")
3005 isASR = true;
3006 else {
3007 Error(S, "shift operator 'asr' or 'lsl' expected");
3008 return MatchOperand_ParseFail;
3009 }
3010 Parser.Lex(); // Eat the operator.
3011
3012 // A '#' and a shift amount.
3013 if (Parser.getTok().isNot(AsmToken::Hash)) {
3014 Error(Parser.getTok().getLoc(), "'#' expected");
3015 return MatchOperand_ParseFail;
3016 }
3017 Parser.Lex(); // Eat hash token.
3018
3019 const MCExpr *ShiftAmount;
3020 SMLoc E = Parser.getTok().getLoc();
3021 if (getParser().ParseExpression(ShiftAmount)) {
3022 Error(E, "malformed shift expression");
3023 return MatchOperand_ParseFail;
3024 }
3025 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3026 if (!CE) {
3027 Error(E, "shift amount must be an immediate");
3028 return MatchOperand_ParseFail;
3029 }
3030
3031 int64_t Val = CE->getValue();
3032 if (isASR) {
3033 // Shift amount must be in [1,32]
3034 if (Val < 1 || Val > 32) {
3035 Error(E, "'asr' shift amount must be in range [1,32]");
3036 return MatchOperand_ParseFail;
3037 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003038 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3039 if (isThumb() && Val == 32) {
3040 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3041 return MatchOperand_ParseFail;
3042 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003043 if (Val == 32) Val = 0;
3044 } else {
3045 // Shift amount must be in [1,32]
3046 if (Val < 0 || Val > 31) {
3047 Error(E, "'lsr' shift amount must be in range [0,31]");
3048 return MatchOperand_ParseFail;
3049 }
3050 }
3051
3052 E = Parser.getTok().getLoc();
3053 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3054
3055 return MatchOperand_Success;
3056}
3057
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003058/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3059/// of instructions. Legal values are:
3060/// ror #n 'n' in {0, 8, 16, 24}
3061ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3062parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3063 const AsmToken &Tok = Parser.getTok();
3064 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003065 if (Tok.isNot(AsmToken::Identifier))
3066 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003067 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003068 if (ShiftName != "ror" && ShiftName != "ROR")
3069 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003070 Parser.Lex(); // Eat the operator.
3071
3072 // A '#' and a rotate amount.
3073 if (Parser.getTok().isNot(AsmToken::Hash)) {
3074 Error(Parser.getTok().getLoc(), "'#' expected");
3075 return MatchOperand_ParseFail;
3076 }
3077 Parser.Lex(); // Eat hash token.
3078
3079 const MCExpr *ShiftAmount;
3080 SMLoc E = Parser.getTok().getLoc();
3081 if (getParser().ParseExpression(ShiftAmount)) {
3082 Error(E, "malformed rotate expression");
3083 return MatchOperand_ParseFail;
3084 }
3085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3086 if (!CE) {
3087 Error(E, "rotate amount must be an immediate");
3088 return MatchOperand_ParseFail;
3089 }
3090
3091 int64_t Val = CE->getValue();
3092 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3093 // normally, zero is represented in asm by omitting the rotate operand
3094 // entirely.
3095 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3096 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3097 return MatchOperand_ParseFail;
3098 }
3099
3100 E = Parser.getTok().getLoc();
3101 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3102
3103 return MatchOperand_Success;
3104}
3105
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003106ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3107parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3108 SMLoc S = Parser.getTok().getLoc();
3109 // The bitfield descriptor is really two operands, the LSB and the width.
3110 if (Parser.getTok().isNot(AsmToken::Hash)) {
3111 Error(Parser.getTok().getLoc(), "'#' expected");
3112 return MatchOperand_ParseFail;
3113 }
3114 Parser.Lex(); // Eat hash token.
3115
3116 const MCExpr *LSBExpr;
3117 SMLoc E = Parser.getTok().getLoc();
3118 if (getParser().ParseExpression(LSBExpr)) {
3119 Error(E, "malformed immediate expression");
3120 return MatchOperand_ParseFail;
3121 }
3122 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3123 if (!CE) {
3124 Error(E, "'lsb' operand must be an immediate");
3125 return MatchOperand_ParseFail;
3126 }
3127
3128 int64_t LSB = CE->getValue();
3129 // The LSB must be in the range [0,31]
3130 if (LSB < 0 || LSB > 31) {
3131 Error(E, "'lsb' operand must be in the range [0,31]");
3132 return MatchOperand_ParseFail;
3133 }
3134 E = Parser.getTok().getLoc();
3135
3136 // Expect another immediate operand.
3137 if (Parser.getTok().isNot(AsmToken::Comma)) {
3138 Error(Parser.getTok().getLoc(), "too few operands");
3139 return MatchOperand_ParseFail;
3140 }
3141 Parser.Lex(); // Eat hash token.
3142 if (Parser.getTok().isNot(AsmToken::Hash)) {
3143 Error(Parser.getTok().getLoc(), "'#' expected");
3144 return MatchOperand_ParseFail;
3145 }
3146 Parser.Lex(); // Eat hash token.
3147
3148 const MCExpr *WidthExpr;
3149 if (getParser().ParseExpression(WidthExpr)) {
3150 Error(E, "malformed immediate expression");
3151 return MatchOperand_ParseFail;
3152 }
3153 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3154 if (!CE) {
3155 Error(E, "'width' operand must be an immediate");
3156 return MatchOperand_ParseFail;
3157 }
3158
3159 int64_t Width = CE->getValue();
3160 // The LSB must be in the range [1,32-lsb]
3161 if (Width < 1 || Width > 32 - LSB) {
3162 Error(E, "'width' operand must be in the range [1,32-lsb]");
3163 return MatchOperand_ParseFail;
3164 }
3165 E = Parser.getTok().getLoc();
3166
3167 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3168
3169 return MatchOperand_Success;
3170}
3171
Jim Grosbach7ce05792011-08-03 23:50:40 +00003172ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3173parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3174 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003175 // postidx_reg := '+' register {, shift}
3176 // | '-' register {, shift}
3177 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003178
3179 // This method must return MatchOperand_NoMatch without consuming any tokens
3180 // in the case where there is no match, as other alternatives take other
3181 // parse methods.
3182 AsmToken Tok = Parser.getTok();
3183 SMLoc S = Tok.getLoc();
3184 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003185 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003186 int Reg = -1;
3187 if (Tok.is(AsmToken::Plus)) {
3188 Parser.Lex(); // Eat the '+' token.
3189 haveEaten = true;
3190 } else if (Tok.is(AsmToken::Minus)) {
3191 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003192 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003193 haveEaten = true;
3194 }
3195 if (Parser.getTok().is(AsmToken::Identifier))
3196 Reg = tryParseRegister();
3197 if (Reg == -1) {
3198 if (!haveEaten)
3199 return MatchOperand_NoMatch;
3200 Error(Parser.getTok().getLoc(), "register expected");
3201 return MatchOperand_ParseFail;
3202 }
3203 SMLoc E = Parser.getTok().getLoc();
3204
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003205 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3206 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003207 if (Parser.getTok().is(AsmToken::Comma)) {
3208 Parser.Lex(); // Eat the ','.
3209 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3210 return MatchOperand_ParseFail;
3211 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003212
3213 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3214 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003215
3216 return MatchOperand_Success;
3217}
3218
Jim Grosbach251bf252011-08-10 21:56:18 +00003219ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3220parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3221 // Check for a post-index addressing register operand. Specifically:
3222 // am3offset := '+' register
3223 // | '-' register
3224 // | register
3225 // | # imm
3226 // | # + imm
3227 // | # - imm
3228
3229 // This method must return MatchOperand_NoMatch without consuming any tokens
3230 // in the case where there is no match, as other alternatives take other
3231 // parse methods.
3232 AsmToken Tok = Parser.getTok();
3233 SMLoc S = Tok.getLoc();
3234
3235 // Do immediates first, as we always parse those if we have a '#'.
3236 if (Parser.getTok().is(AsmToken::Hash)) {
3237 Parser.Lex(); // Eat the '#'.
3238 // Explicitly look for a '-', as we need to encode negative zero
3239 // differently.
3240 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3241 const MCExpr *Offset;
3242 if (getParser().ParseExpression(Offset))
3243 return MatchOperand_ParseFail;
3244 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3245 if (!CE) {
3246 Error(S, "constant expression expected");
3247 return MatchOperand_ParseFail;
3248 }
3249 SMLoc E = Tok.getLoc();
3250 // Negative zero is encoded as the flag value INT32_MIN.
3251 int32_t Val = CE->getValue();
3252 if (isNegative && Val == 0)
3253 Val = INT32_MIN;
3254
3255 Operands.push_back(
3256 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3257
3258 return MatchOperand_Success;
3259 }
3260
3261
3262 bool haveEaten = false;
3263 bool isAdd = true;
3264 int Reg = -1;
3265 if (Tok.is(AsmToken::Plus)) {
3266 Parser.Lex(); // Eat the '+' token.
3267 haveEaten = true;
3268 } else if (Tok.is(AsmToken::Minus)) {
3269 Parser.Lex(); // Eat the '-' token.
3270 isAdd = false;
3271 haveEaten = true;
3272 }
3273 if (Parser.getTok().is(AsmToken::Identifier))
3274 Reg = tryParseRegister();
3275 if (Reg == -1) {
3276 if (!haveEaten)
3277 return MatchOperand_NoMatch;
3278 Error(Parser.getTok().getLoc(), "register expected");
3279 return MatchOperand_ParseFail;
3280 }
3281 SMLoc E = Parser.getTok().getLoc();
3282
3283 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3284 0, S, E));
3285
3286 return MatchOperand_Success;
3287}
3288
Jim Grosbacha77295d2011-09-08 22:07:06 +00003289/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3290/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3291/// when they refer multiple MIOperands inside a single one.
3292bool ARMAsmParser::
3293cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3294 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3295 // Rt, Rt2
3296 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3297 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3298 // Create a writeback register dummy placeholder.
3299 Inst.addOperand(MCOperand::CreateReg(0));
3300 // addr
3301 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3302 // pred
3303 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3304 return true;
3305}
3306
3307/// cvtT2StrdPre - Convert parsed operands to MCInst.
3308/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3309/// when they refer multiple MIOperands inside a single one.
3310bool ARMAsmParser::
3311cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3312 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3313 // Create a writeback register dummy placeholder.
3314 Inst.addOperand(MCOperand::CreateReg(0));
3315 // Rt, Rt2
3316 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3317 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3318 // addr
3319 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3320 // pred
3321 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3322 return true;
3323}
3324
Jim Grosbacheeec0252011-09-08 00:39:19 +00003325/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3326/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3327/// when they refer multiple MIOperands inside a single one.
3328bool ARMAsmParser::
3329cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3331 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3332
3333 // Create a writeback register dummy placeholder.
3334 Inst.addOperand(MCOperand::CreateImm(0));
3335
3336 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3337 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3338 return true;
3339}
3340
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003341/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3342/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3343/// when they refer multiple MIOperands inside a single one.
3344bool ARMAsmParser::
3345cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3346 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3347 // Create a writeback register dummy placeholder.
3348 Inst.addOperand(MCOperand::CreateImm(0));
3349 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3350 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3351 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3352 return true;
3353}
3354
Jim Grosbach1355cf12011-07-26 17:10:22 +00003355/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003356/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3357/// when they refer multiple MIOperands inside a single one.
3358bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003359cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003360 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3361 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3362
3363 // Create a writeback register dummy placeholder.
3364 Inst.addOperand(MCOperand::CreateImm(0));
3365
Jim Grosbach7ce05792011-08-03 23:50:40 +00003366 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003367 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3368 return true;
3369}
3370
Owen Anderson9ab0f252011-08-26 20:43:14 +00003371/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3372/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3373/// when they refer multiple MIOperands inside a single one.
3374bool ARMAsmParser::
3375cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3376 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3377 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3378
3379 // Create a writeback register dummy placeholder.
3380 Inst.addOperand(MCOperand::CreateImm(0));
3381
3382 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3383 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3384 return true;
3385}
3386
3387
Jim Grosbach548340c2011-08-11 19:22:40 +00003388/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3389/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3390/// when they refer multiple MIOperands inside a single one.
3391bool ARMAsmParser::
3392cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3393 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3394 // Create a writeback register dummy placeholder.
3395 Inst.addOperand(MCOperand::CreateImm(0));
3396 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3397 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3398 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3399 return true;
3400}
3401
Jim Grosbach1355cf12011-07-26 17:10:22 +00003402/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003403/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3404/// when they refer multiple MIOperands inside a single one.
3405bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003406cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003407 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3408 // Create a writeback register dummy placeholder.
3409 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003410 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3411 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3412 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003413 return true;
3414}
3415
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003416/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3417/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3418/// when they refer multiple MIOperands inside a single one.
3419bool ARMAsmParser::
3420cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3421 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3422 // Create a writeback register dummy placeholder.
3423 Inst.addOperand(MCOperand::CreateImm(0));
3424 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3425 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3426 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3427 return true;
3428}
3429
Jim Grosbach7ce05792011-08-03 23:50:40 +00003430/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3431/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3432/// when they refer multiple MIOperands inside a single one.
3433bool ARMAsmParser::
3434cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3435 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3436 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003437 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003438 // Create a writeback register dummy placeholder.
3439 Inst.addOperand(MCOperand::CreateImm(0));
3440 // addr
3441 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3442 // offset
3443 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3444 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003445 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3446 return true;
3447}
3448
Jim Grosbach7ce05792011-08-03 23:50:40 +00003449/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003450/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3451/// when they refer multiple MIOperands inside a single one.
3452bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003453cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3454 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3455 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003456 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003457 // Create a writeback register dummy placeholder.
3458 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003459 // addr
3460 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3461 // offset
3462 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3463 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003464 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3465 return true;
3466}
3467
Jim Grosbach7ce05792011-08-03 23:50:40 +00003468/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003469/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3470/// when they refer multiple MIOperands inside a single one.
3471bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003472cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3473 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003474 // Create a writeback register dummy placeholder.
3475 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003476 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003477 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003478 // addr
3479 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3480 // offset
3481 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3482 // pred
3483 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3484 return true;
3485}
3486
3487/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3488/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3489/// when they refer multiple MIOperands inside a single one.
3490bool ARMAsmParser::
3491cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3492 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3493 // Create a writeback register dummy placeholder.
3494 Inst.addOperand(MCOperand::CreateImm(0));
3495 // Rt
3496 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3497 // addr
3498 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3499 // offset
3500 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3501 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003502 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3503 return true;
3504}
3505
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003506/// cvtLdrdPre - Convert parsed operands to MCInst.
3507/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3508/// when they refer multiple MIOperands inside a single one.
3509bool ARMAsmParser::
3510cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3511 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3512 // Rt, Rt2
3513 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3514 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3515 // Create a writeback register dummy placeholder.
3516 Inst.addOperand(MCOperand::CreateImm(0));
3517 // addr
3518 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3519 // pred
3520 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3521 return true;
3522}
3523
Jim Grosbach14605d12011-08-11 20:28:23 +00003524/// cvtStrdPre - Convert parsed operands to MCInst.
3525/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3526/// when they refer multiple MIOperands inside a single one.
3527bool ARMAsmParser::
3528cvtStrdPre(MCInst &Inst, unsigned Opcode,
3529 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3530 // Create a writeback register dummy placeholder.
3531 Inst.addOperand(MCOperand::CreateImm(0));
3532 // Rt, Rt2
3533 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3534 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3535 // addr
3536 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3537 // pred
3538 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3539 return true;
3540}
3541
Jim Grosbach623a4542011-08-10 22:42:16 +00003542/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3543/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3544/// when they refer multiple MIOperands inside a single one.
3545bool ARMAsmParser::
3546cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3547 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3548 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3549 // Create a writeback register dummy placeholder.
3550 Inst.addOperand(MCOperand::CreateImm(0));
3551 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3552 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3553 return true;
3554}
3555
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003556/// cvtThumbMultiple- Convert parsed operands to MCInst.
3557/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3558/// when they refer multiple MIOperands inside a single one.
3559bool ARMAsmParser::
3560cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3561 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 // The second source operand must be the same register as the destination
3563 // operand.
3564 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003565 (((ARMOperand*)Operands[3])->getReg() !=
3566 ((ARMOperand*)Operands[5])->getReg()) &&
3567 (((ARMOperand*)Operands[3])->getReg() !=
3568 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003569 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003570 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003571 return false;
3572 }
3573 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3574 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003575 // If we have a three-operand form, make sure to set Rn to be the operand
3576 // that isn't the same as Rd.
3577 unsigned RegOp = 4;
3578 if (Operands.size() == 6 &&
3579 ((ARMOperand*)Operands[4])->getReg() ==
3580 ((ARMOperand*)Operands[3])->getReg())
3581 RegOp = 5;
3582 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3583 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003584 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3585
3586 return true;
3587}
Jim Grosbach623a4542011-08-10 22:42:16 +00003588
Jim Grosbach12431322011-10-24 22:16:58 +00003589bool ARMAsmParser::
3590cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3591 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3592 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003593 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003594 // Create a writeback register dummy placeholder.
3595 Inst.addOperand(MCOperand::CreateImm(0));
3596 // Vn
3597 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3598 // pred
3599 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3600 return true;
3601}
3602
3603bool ARMAsmParser::
3604cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3605 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3606 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003607 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003608 // Create a writeback register dummy placeholder.
3609 Inst.addOperand(MCOperand::CreateImm(0));
3610 // Vn
3611 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3612 // Vm
3613 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3614 // pred
3615 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3616 return true;
3617}
3618
Jim Grosbach4334e032011-10-31 21:50:31 +00003619bool ARMAsmParser::
3620cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3621 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3622 // Create a writeback register dummy placeholder.
3623 Inst.addOperand(MCOperand::CreateImm(0));
3624 // Vn
3625 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3626 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003627 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003628 // pred
3629 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3630 return true;
3631}
3632
3633bool ARMAsmParser::
3634cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3635 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3636 // Create a writeback register dummy placeholder.
3637 Inst.addOperand(MCOperand::CreateImm(0));
3638 // Vn
3639 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3640 // Vm
3641 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3642 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003643 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003644 // pred
3645 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3646 return true;
3647}
3648
Bill Wendlinge7176102010-11-06 22:36:58 +00003649/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003650/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003651bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003652parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003653 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003654 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003655 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003656 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003657 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003658
Sean Callanan18b83232010-01-19 21:44:56 +00003659 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003660 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003661 if (BaseRegNum == -1)
3662 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003663
Daniel Dunbar05710932011-01-18 05:34:17 +00003664 // The next token must either be a comma or a closing bracket.
3665 const AsmToken &Tok = Parser.getTok();
3666 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003667 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003668
Jim Grosbach7ce05792011-08-03 23:50:40 +00003669 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003670 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003671 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003672
Jim Grosbach7ce05792011-08-03 23:50:40 +00003673 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003674 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003675
Jim Grosbachfb12f352011-09-19 18:42:21 +00003676 // If there's a pre-indexing writeback marker, '!', just add it as a token
3677 // operand. It's rather odd, but syntactically valid.
3678 if (Parser.getTok().is(AsmToken::Exclaim)) {
3679 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3680 Parser.Lex(); // Eat the '!'.
3681 }
3682
Jim Grosbach7ce05792011-08-03 23:50:40 +00003683 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003684 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003685
Jim Grosbach7ce05792011-08-03 23:50:40 +00003686 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3687 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003688
Jim Grosbach57dcb852011-10-11 17:29:55 +00003689 // If we have a ':', it's an alignment specifier.
3690 if (Parser.getTok().is(AsmToken::Colon)) {
3691 Parser.Lex(); // Eat the ':'.
3692 E = Parser.getTok().getLoc();
3693
3694 const MCExpr *Expr;
3695 if (getParser().ParseExpression(Expr))
3696 return true;
3697
3698 // The expression has to be a constant. Memory references with relocations
3699 // don't come through here, as they use the <label> forms of the relevant
3700 // instructions.
3701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3702 if (!CE)
3703 return Error (E, "constant expression expected");
3704
3705 unsigned Align = 0;
3706 switch (CE->getValue()) {
3707 default:
3708 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3709 case 64: Align = 8; break;
3710 case 128: Align = 16; break;
3711 case 256: Align = 32; break;
3712 }
3713
3714 // Now we should have the closing ']'
3715 E = Parser.getTok().getLoc();
3716 if (Parser.getTok().isNot(AsmToken::RBrac))
3717 return Error(E, "']' expected");
3718 Parser.Lex(); // Eat right bracket token.
3719
3720 // Don't worry about range checking the value here. That's handled by
3721 // the is*() predicates.
3722 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3723 ARM_AM::no_shift, 0, Align,
3724 false, S, E));
3725
3726 // If there's a pre-indexing writeback marker, '!', just add it as a token
3727 // operand.
3728 if (Parser.getTok().is(AsmToken::Exclaim)) {
3729 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3730 Parser.Lex(); // Eat the '!'.
3731 }
3732
3733 return false;
3734 }
3735
3736 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003737 // offset. Be friendly and also accept a plain integer (without a leading
3738 // hash) for gas compatibility.
3739 if (Parser.getTok().is(AsmToken::Hash) ||
3740 Parser.getTok().is(AsmToken::Integer)) {
3741 if (Parser.getTok().is(AsmToken::Hash))
3742 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003743 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003744
Owen Anderson0da10cf2011-08-29 19:36:44 +00003745 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003746 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003747 if (getParser().ParseExpression(Offset))
3748 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003749
3750 // The expression has to be a constant. Memory references with relocations
3751 // don't come through here, as they use the <label> forms of the relevant
3752 // instructions.
3753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3754 if (!CE)
3755 return Error (E, "constant expression expected");
3756
Owen Anderson0da10cf2011-08-29 19:36:44 +00003757 // If the constant was #-0, represent it as INT32_MIN.
3758 int32_t Val = CE->getValue();
3759 if (isNegative && Val == 0)
3760 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3761
Jim Grosbach7ce05792011-08-03 23:50:40 +00003762 // Now we should have the closing ']'
3763 E = Parser.getTok().getLoc();
3764 if (Parser.getTok().isNot(AsmToken::RBrac))
3765 return Error(E, "']' expected");
3766 Parser.Lex(); // Eat right bracket token.
3767
3768 // Don't worry about range checking the value here. That's handled by
3769 // the is*() predicates.
3770 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003771 ARM_AM::no_shift, 0, 0,
3772 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003773
3774 // If there's a pre-indexing writeback marker, '!', just add it as a token
3775 // operand.
3776 if (Parser.getTok().is(AsmToken::Exclaim)) {
3777 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3778 Parser.Lex(); // Eat the '!'.
3779 }
3780
3781 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003782 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003783
3784 // The register offset is optionally preceded by a '+' or '-'
3785 bool isNegative = false;
3786 if (Parser.getTok().is(AsmToken::Minus)) {
3787 isNegative = true;
3788 Parser.Lex(); // Eat the '-'.
3789 } else if (Parser.getTok().is(AsmToken::Plus)) {
3790 // Nothing to do.
3791 Parser.Lex(); // Eat the '+'.
3792 }
3793
3794 E = Parser.getTok().getLoc();
3795 int OffsetRegNum = tryParseRegister();
3796 if (OffsetRegNum == -1)
3797 return Error(E, "register expected");
3798
3799 // If there's a shift operator, handle it.
3800 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003801 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003802 if (Parser.getTok().is(AsmToken::Comma)) {
3803 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003804 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003805 return true;
3806 }
3807
3808 // Now we should have the closing ']'
3809 E = Parser.getTok().getLoc();
3810 if (Parser.getTok().isNot(AsmToken::RBrac))
3811 return Error(E, "']' expected");
3812 Parser.Lex(); // Eat right bracket token.
3813
3814 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003815 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003816 S, E));
3817
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003818 // If there's a pre-indexing writeback marker, '!', just add it as a token
3819 // operand.
3820 if (Parser.getTok().is(AsmToken::Exclaim)) {
3821 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3822 Parser.Lex(); // Eat the '!'.
3823 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003824
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003825 return false;
3826}
3827
Jim Grosbach7ce05792011-08-03 23:50:40 +00003828/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003829/// ( lsl | lsr | asr | ror ) , # shift_amount
3830/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003831/// return true if it parses a shift otherwise it returns false.
3832bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3833 unsigned &Amount) {
3834 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003835 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003836 if (Tok.isNot(AsmToken::Identifier))
3837 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003838 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003839 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003840 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003841 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003842 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003843 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003844 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003845 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003846 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003847 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003848 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003849 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003850 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003851 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003852
Jim Grosbach7ce05792011-08-03 23:50:40 +00003853 // rrx stands alone.
3854 Amount = 0;
3855 if (St != ARM_AM::rrx) {
3856 Loc = Parser.getTok().getLoc();
3857 // A '#' and a shift amount.
3858 const AsmToken &HashTok = Parser.getTok();
3859 if (HashTok.isNot(AsmToken::Hash))
3860 return Error(HashTok.getLoc(), "'#' expected");
3861 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003862
Jim Grosbach7ce05792011-08-03 23:50:40 +00003863 const MCExpr *Expr;
3864 if (getParser().ParseExpression(Expr))
3865 return true;
3866 // Range check the immediate.
3867 // lsl, ror: 0 <= imm <= 31
3868 // lsr, asr: 0 <= imm <= 32
3869 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3870 if (!CE)
3871 return Error(Loc, "shift amount must be an immediate");
3872 int64_t Imm = CE->getValue();
3873 if (Imm < 0 ||
3874 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3875 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3876 return Error(Loc, "immediate shift value out of range");
3877 Amount = Imm;
3878 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003879
3880 return false;
3881}
3882
Jim Grosbach9d390362011-10-03 23:38:36 +00003883/// parseFPImm - A floating point immediate expression operand.
3884ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3885parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3886 SMLoc S = Parser.getTok().getLoc();
3887
3888 if (Parser.getTok().isNot(AsmToken::Hash))
3889 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003890
3891 // Disambiguate the VMOV forms that can accept an FP immediate.
3892 // vmov.f32 <sreg>, #imm
3893 // vmov.f64 <dreg>, #imm
3894 // vmov.f32 <dreg>, #imm @ vector f32x2
3895 // vmov.f32 <qreg>, #imm @ vector f32x4
3896 //
3897 // There are also the NEON VMOV instructions which expect an
3898 // integer constant. Make sure we don't try to parse an FPImm
3899 // for these:
3900 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3901 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3902 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3903 TyOp->getToken() != ".f64"))
3904 return MatchOperand_NoMatch;
3905
Jim Grosbach9d390362011-10-03 23:38:36 +00003906 Parser.Lex(); // Eat the '#'.
3907
3908 // Handle negation, as that still comes through as a separate token.
3909 bool isNegative = false;
3910 if (Parser.getTok().is(AsmToken::Minus)) {
3911 isNegative = true;
3912 Parser.Lex();
3913 }
3914 const AsmToken &Tok = Parser.getTok();
3915 if (Tok.is(AsmToken::Real)) {
3916 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3917 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3918 // If we had a '-' in front, toggle the sign bit.
3919 IntVal ^= (uint64_t)isNegative << 63;
3920 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3921 Parser.Lex(); // Eat the token.
3922 if (Val == -1) {
3923 TokError("floating point value out of range");
3924 return MatchOperand_ParseFail;
3925 }
3926 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3927 return MatchOperand_Success;
3928 }
3929 if (Tok.is(AsmToken::Integer)) {
3930 int64_t Val = Tok.getIntVal();
3931 Parser.Lex(); // Eat the token.
3932 if (Val > 255 || Val < 0) {
3933 TokError("encoded floating point value out of range");
3934 return MatchOperand_ParseFail;
3935 }
3936 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3937 return MatchOperand_Success;
3938 }
3939
3940 TokError("invalid floating point immediate");
3941 return MatchOperand_ParseFail;
3942}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003943/// Parse a arm instruction operand. For now this parses the operand regardless
3944/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003945bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003946 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003947 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003948
3949 // Check if the current operand has a custom associated parser, if so, try to
3950 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003951 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3952 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003953 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003954 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3955 // there was a match, but an error occurred, in which case, just return that
3956 // the operand parsing failed.
3957 if (ResTy == MatchOperand_ParseFail)
3958 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003959
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003960 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003961 default:
3962 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003963 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003964 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003965 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003966 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003967 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003968 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003969 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003970 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003971 else if (Res == -1) // irrecoverable error
3972 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003973 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3974 S = Parser.getTok().getLoc();
3975 Parser.Lex();
3976 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3977 return false;
3978 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003979
3980 // Fall though for the Identifier case that is not a register or a
3981 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003982 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003983 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003984 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003985 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003986 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003987 // This was not a register so parse other operands that start with an
3988 // identifier (like labels) as expressions and create them as immediates.
3989 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003990 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003991 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003992 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003993 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003994 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3995 return false;
3996 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003997 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003998 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003999 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004000 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004001 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004002 // #42 -> immediate.
4003 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004004 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004005 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004006 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004007 const MCExpr *ImmVal;
4008 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004009 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004010 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004011 if (CE) {
4012 int32_t Val = CE->getValue();
4013 if (isNegative && Val == 0)
4014 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004015 }
Sean Callanan76264762010-04-02 22:27:05 +00004016 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004017 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4018 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004019 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004020 case AsmToken::Colon: {
4021 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004022 // FIXME: Check it's an expression prefix,
4023 // e.g. (FOO - :lower16:BAR) isn't legal.
4024 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004025 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004026 return true;
4027
Evan Cheng75972122011-01-13 07:58:56 +00004028 const MCExpr *SubExprVal;
4029 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004030 return true;
4031
Evan Cheng75972122011-01-13 07:58:56 +00004032 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4033 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004034 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004035 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004036 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004037 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004038 }
4039}
4040
Jim Grosbach1355cf12011-07-26 17:10:22 +00004041// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004042// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004043bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004044 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004045
4046 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004047 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004048 Parser.Lex(); // Eat ':'
4049
4050 if (getLexer().isNot(AsmToken::Identifier)) {
4051 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4052 return true;
4053 }
4054
4055 StringRef IDVal = Parser.getTok().getIdentifier();
4056 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004057 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004058 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004059 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004060 } else {
4061 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4062 return true;
4063 }
4064 Parser.Lex();
4065
4066 if (getLexer().isNot(AsmToken::Colon)) {
4067 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4068 return true;
4069 }
4070 Parser.Lex(); // Eat the last ':'
4071 return false;
4072}
4073
Daniel Dunbar352e1482011-01-11 15:59:50 +00004074/// \brief Given a mnemonic, split out possible predication code and carry
4075/// setting letters to form a canonical mnemonic and flags.
4076//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004077// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004078// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004079StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004080 unsigned &PredicationCode,
4081 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004082 unsigned &ProcessorIMod,
4083 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004084 PredicationCode = ARMCC::AL;
4085 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004086 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004087
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004088 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004089 //
4090 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004091 if ((Mnemonic == "movs" && isThumb()) ||
4092 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4093 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4094 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4095 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4096 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4097 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4098 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004099 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004100
Jim Grosbach3f00e312011-07-11 17:09:57 +00004101 // First, split out any predication code. Ignore mnemonics we know aren't
4102 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004103 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004104 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004105 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004106 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004107 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4108 .Case("eq", ARMCC::EQ)
4109 .Case("ne", ARMCC::NE)
4110 .Case("hs", ARMCC::HS)
4111 .Case("cs", ARMCC::HS)
4112 .Case("lo", ARMCC::LO)
4113 .Case("cc", ARMCC::LO)
4114 .Case("mi", ARMCC::MI)
4115 .Case("pl", ARMCC::PL)
4116 .Case("vs", ARMCC::VS)
4117 .Case("vc", ARMCC::VC)
4118 .Case("hi", ARMCC::HI)
4119 .Case("ls", ARMCC::LS)
4120 .Case("ge", ARMCC::GE)
4121 .Case("lt", ARMCC::LT)
4122 .Case("gt", ARMCC::GT)
4123 .Case("le", ARMCC::LE)
4124 .Case("al", ARMCC::AL)
4125 .Default(~0U);
4126 if (CC != ~0U) {
4127 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4128 PredicationCode = CC;
4129 }
Bill Wendling52925b62010-10-29 23:50:21 +00004130 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004131
Daniel Dunbar352e1482011-01-11 15:59:50 +00004132 // Next, determine if we have a carry setting bit. We explicitly ignore all
4133 // the instructions we know end in 's'.
4134 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004135 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004136 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4137 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4138 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004139 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4140 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004141 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4142 CarrySetting = true;
4143 }
4144
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004145 // The "cps" instruction can have a interrupt mode operand which is glued into
4146 // the mnemonic. Check if this is the case, split it and parse the imod op
4147 if (Mnemonic.startswith("cps")) {
4148 // Split out any imod code.
4149 unsigned IMod =
4150 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4151 .Case("ie", ARM_PROC::IE)
4152 .Case("id", ARM_PROC::ID)
4153 .Default(~0U);
4154 if (IMod != ~0U) {
4155 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4156 ProcessorIMod = IMod;
4157 }
4158 }
4159
Jim Grosbach89df9962011-08-26 21:43:41 +00004160 // The "it" instruction has the condition mask on the end of the mnemonic.
4161 if (Mnemonic.startswith("it")) {
4162 ITMask = Mnemonic.slice(2, Mnemonic.size());
4163 Mnemonic = Mnemonic.slice(0, 2);
4164 }
4165
Daniel Dunbar352e1482011-01-11 15:59:50 +00004166 return Mnemonic;
4167}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004168
4169/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4170/// inclusion of carry set or predication code operands.
4171//
4172// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004173void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004174getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004175 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004176 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4177 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004178 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004179 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004180 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004181 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004182 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004183 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004184 Mnemonic == "mla" || Mnemonic == "smlal" ||
4185 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004186 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004187 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004188 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004189
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004190 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4191 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4192 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4193 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004194 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4195 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004196 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004197 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4198 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4199 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004200 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4201 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004202 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004203 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004204 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004205 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004206
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004207 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004208 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004209 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004210 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004211 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004212}
4213
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004214bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4215 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004216 // FIXME: This is all horribly hacky. We really need a better way to deal
4217 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004218
4219 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4220 // another does not. Specifically, the MOVW instruction does not. So we
4221 // special case it here and remove the defaulted (non-setting) cc_out
4222 // operand if that's the instruction we're trying to match.
4223 //
4224 // We do this as post-processing of the explicit operands rather than just
4225 // conditionally adding the cc_out in the first place because we need
4226 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004227 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004228 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4229 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4230 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4231 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004232
4233 // Register-register 'add' for thumb does not have a cc_out operand
4234 // when there are only two register operands.
4235 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4236 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4237 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4238 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4239 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004240 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004241 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4242 // have to check the immediate range here since Thumb2 has a variant
4243 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004244 if (((isThumb() && Mnemonic == "add") ||
4245 (isThumbTwo() && Mnemonic == "sub")) &&
4246 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004247 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4248 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4249 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004250 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4251 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4252 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004253 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004254 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4255 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004256 // selecting via the generic "add" mnemonic, so to know that we
4257 // should remove the cc_out operand, we have to explicitly check that
4258 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004259 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4260 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004261 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4262 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4263 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4264 // Nest conditions rather than one big 'if' statement for readability.
4265 //
4266 // If either register is a high reg, it's either one of the SP
4267 // variants (handled above) or a 32-bit encoding, so we just
4268 // check against T3.
4269 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4270 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4271 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4272 return false;
4273 // If both registers are low, we're in an IT block, and the immediate is
4274 // in range, we should use encoding T1 instead, which has a cc_out.
4275 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004276 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004277 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4278 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4279 return false;
4280
4281 // Otherwise, we use encoding T4, which does not have a cc_out
4282 // operand.
4283 return true;
4284 }
4285
Jim Grosbach64944f42011-09-14 21:00:40 +00004286 // The thumb2 multiply instruction doesn't have a CCOut register, so
4287 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4288 // use the 16-bit encoding or not.
4289 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4290 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4291 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4292 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4293 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4294 // If the registers aren't low regs, the destination reg isn't the
4295 // same as one of the source regs, or the cc_out operand is zero
4296 // outside of an IT block, we have to use the 32-bit encoding, so
4297 // remove the cc_out operand.
4298 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4299 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004300 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004301 !inITBlock() ||
4302 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4303 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4304 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4305 static_cast<ARMOperand*>(Operands[4])->getReg())))
4306 return true;
4307
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004308 // Also check the 'mul' syntax variant that doesn't specify an explicit
4309 // destination register.
4310 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4311 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4312 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4313 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4314 // If the registers aren't low regs or the cc_out operand is zero
4315 // outside of an IT block, we have to use the 32-bit encoding, so
4316 // remove the cc_out operand.
4317 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4318 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4319 !inITBlock()))
4320 return true;
4321
Jim Grosbach64944f42011-09-14 21:00:40 +00004322
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004323
Jim Grosbachf69c8042011-08-24 21:42:27 +00004324 // Register-register 'add/sub' for thumb does not have a cc_out operand
4325 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4326 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4327 // right, this will result in better diagnostics (which operand is off)
4328 // anyway.
4329 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4330 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004331 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4332 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4333 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4334 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004335
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004336 return false;
4337}
4338
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004339static bool isDataTypeToken(StringRef Tok) {
4340 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4341 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4342 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4343 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4344 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4345 Tok == ".f" || Tok == ".d";
4346}
4347
4348// FIXME: This bit should probably be handled via an explicit match class
4349// in the .td files that matches the suffix instead of having it be
4350// a literal string token the way it is now.
4351static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4352 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4353}
4354
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004355/// Parse an arm instruction mnemonic followed by its operands.
4356bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4357 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4358 // Create the leading tokens for the mnemonic, split by '.' characters.
4359 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004360 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004361
Daniel Dunbar352e1482011-01-11 15:59:50 +00004362 // Split out the predication code and carry setting flag from the mnemonic.
4363 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004364 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004365 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004366 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004367 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004368 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004369
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004370 // In Thumb1, only the branch (B) instruction can be predicated.
4371 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4372 Parser.EatToEndOfStatement();
4373 return Error(NameLoc, "conditional execution not supported in Thumb1");
4374 }
4375
Jim Grosbachffa32252011-07-19 19:13:28 +00004376 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4377
Jim Grosbach89df9962011-08-26 21:43:41 +00004378 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4379 // is the mask as it will be for the IT encoding if the conditional
4380 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4381 // where the conditional bit0 is zero, the instruction post-processing
4382 // will adjust the mask accordingly.
4383 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004384 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4385 if (ITMask.size() > 3) {
4386 Parser.EatToEndOfStatement();
4387 return Error(Loc, "too many conditions on IT instruction");
4388 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004389 unsigned Mask = 8;
4390 for (unsigned i = ITMask.size(); i != 0; --i) {
4391 char pos = ITMask[i - 1];
4392 if (pos != 't' && pos != 'e') {
4393 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004394 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004395 }
4396 Mask >>= 1;
4397 if (ITMask[i - 1] == 't')
4398 Mask |= 8;
4399 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004400 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004401 }
4402
Jim Grosbachffa32252011-07-19 19:13:28 +00004403 // FIXME: This is all a pretty gross hack. We should automatically handle
4404 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004405
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004406 // Next, add the CCOut and ConditionCode operands, if needed.
4407 //
4408 // For mnemonics which can ever incorporate a carry setting bit or predication
4409 // code, our matching model involves us always generating CCOut and
4410 // ConditionCode operands to match the mnemonic "as written" and then we let
4411 // the matcher deal with finding the right instruction or generating an
4412 // appropriate error.
4413 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004414 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004415
Jim Grosbach33c16a22011-07-14 22:04:21 +00004416 // If we had a carry-set on an instruction that can't do that, issue an
4417 // error.
4418 if (!CanAcceptCarrySet && CarrySetting) {
4419 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004420 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004421 "' can not set flags, but 's' suffix specified");
4422 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004423 // If we had a predication code on an instruction that can't do that, issue an
4424 // error.
4425 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4426 Parser.EatToEndOfStatement();
4427 return Error(NameLoc, "instruction '" + Mnemonic +
4428 "' is not predicable, but condition code specified");
4429 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004430
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004431 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004432 if (CanAcceptCarrySet) {
4433 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004434 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004435 Loc));
4436 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004437
4438 // Add the predication code operand, if necessary.
4439 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004440 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4441 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004442 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004443 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004444 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004445
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004446 // Add the processor imod operand, if necessary.
4447 if (ProcessorIMod) {
4448 Operands.push_back(ARMOperand::CreateImm(
4449 MCConstantExpr::Create(ProcessorIMod, getContext()),
4450 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004451 }
4452
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004453 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004454 while (Next != StringRef::npos) {
4455 Start = Next;
4456 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004457 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004458
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004459 // Some NEON instructions have an optional datatype suffix that is
4460 // completely ignored. Check for that.
4461 if (isDataTypeToken(ExtraToken) &&
4462 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4463 continue;
4464
Jim Grosbach81d2e392011-09-07 16:06:04 +00004465 if (ExtraToken != ".n") {
4466 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4467 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4468 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004469 }
4470
4471 // Read the remaining operands.
4472 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004473 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004474 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004475 Parser.EatToEndOfStatement();
4476 return true;
4477 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004478
4479 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004480 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004481
4482 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004483 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004484 Parser.EatToEndOfStatement();
4485 return true;
4486 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004487 }
4488 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004489
Chris Lattnercbf8a982010-09-11 16:18:25 +00004490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004491 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004492 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004493 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004494 }
Bill Wendling146018f2010-11-06 21:42:12 +00004495
Chris Lattner34e53142010-09-08 05:10:46 +00004496 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004497
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004498 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4499 // do and don't have a cc_out optional-def operand. With some spot-checks
4500 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004501 // parse and adjust accordingly before actually matching. We shouldn't ever
4502 // try to remove a cc_out operand that was explicitly set on the the
4503 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4504 // table driven matcher doesn't fit well with the ARM instruction set.
4505 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004506 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4507 Operands.erase(Operands.begin() + 1);
4508 delete Op;
4509 }
4510
Jim Grosbachcf121c32011-07-28 21:57:55 +00004511 // ARM mode 'blx' need special handling, as the register operand version
4512 // is predicable, but the label operand version is not. So, we can't rely
4513 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004514 // a k_CondCode operand in the list. If we're trying to match the label
4515 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004516 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4517 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4518 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4519 Operands.erase(Operands.begin() + 1);
4520 delete Op;
4521 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004522
4523 // The vector-compare-to-zero instructions have a literal token "#0" at
4524 // the end that comes to here as an immediate operand. Convert it to a
4525 // token to play nicely with the matcher.
4526 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4527 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4528 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4529 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4530 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4531 if (CE && CE->getValue() == 0) {
4532 Operands.erase(Operands.begin() + 5);
4533 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4534 delete Op;
4535 }
4536 }
Jim Grosbach68259142011-10-03 22:30:24 +00004537 // VCMP{E} does the same thing, but with a different operand count.
4538 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4539 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4540 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4542 if (CE && CE->getValue() == 0) {
4543 Operands.erase(Operands.begin() + 4);
4544 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4545 delete Op;
4546 }
4547 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004548 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4549 // end. Convert it to a token here.
4550 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4551 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4552 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4554 if (CE && CE->getValue() == 0) {
4555 Operands.erase(Operands.begin() + 5);
4556 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4557 delete Op;
4558 }
4559 }
4560
Chris Lattner98986712010-01-14 22:21:20 +00004561 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004562}
4563
Jim Grosbach189610f2011-07-26 18:25:39 +00004564// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004565
4566// return 'true' if register list contains non-low GPR registers,
4567// 'false' otherwise. If Reg is in the register list or is HiReg, set
4568// 'containsReg' to true.
4569static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4570 unsigned HiReg, bool &containsReg) {
4571 containsReg = false;
4572 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4573 unsigned OpReg = Inst.getOperand(i).getReg();
4574 if (OpReg == Reg)
4575 containsReg = true;
4576 // Anything other than a low register isn't legal here.
4577 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4578 return true;
4579 }
4580 return false;
4581}
4582
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004583// Check if the specified regisgter is in the register list of the inst,
4584// starting at the indicated operand number.
4585static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4586 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4587 unsigned OpReg = Inst.getOperand(i).getReg();
4588 if (OpReg == Reg)
4589 return true;
4590 }
4591 return false;
4592}
4593
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004594// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4595// the ARMInsts array) instead. Getting that here requires awkward
4596// API changes, though. Better way?
4597namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004598extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004599}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004600static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004601 return ARMInsts[Opcode];
4602}
4603
Jim Grosbach189610f2011-07-26 18:25:39 +00004604// FIXME: We would really like to be able to tablegen'erate this.
4605bool ARMAsmParser::
4606validateInstruction(MCInst &Inst,
4607 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004608 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004609 SMLoc Loc = Operands[0]->getStartLoc();
4610 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004611 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4612 // being allowed in IT blocks, but not being predicable. It just always
4613 // executes.
4614 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004615 unsigned bit = 1;
4616 if (ITState.FirstCond)
4617 ITState.FirstCond = false;
4618 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004619 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004620 // The instruction must be predicable.
4621 if (!MCID.isPredicable())
4622 return Error(Loc, "instructions in IT block must be predicable");
4623 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4624 unsigned ITCond = bit ? ITState.Cond :
4625 ARMCC::getOppositeCondition(ITState.Cond);
4626 if (Cond != ITCond) {
4627 // Find the condition code Operand to get its SMLoc information.
4628 SMLoc CondLoc;
4629 for (unsigned i = 1; i < Operands.size(); ++i)
4630 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4631 CondLoc = Operands[i]->getStartLoc();
4632 return Error(CondLoc, "incorrect condition in IT block; got '" +
4633 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4634 "', but expected '" +
4635 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4636 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004637 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004638 } else if (isThumbTwo() && MCID.isPredicable() &&
4639 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004640 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4641 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004642 return Error(Loc, "predicated instructions must be in IT block");
4643
Jim Grosbach189610f2011-07-26 18:25:39 +00004644 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004645 case ARM::LDRD:
4646 case ARM::LDRD_PRE:
4647 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004648 case ARM::LDREXD: {
4649 // Rt2 must be Rt + 1.
4650 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4651 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4652 if (Rt2 != Rt + 1)
4653 return Error(Operands[3]->getStartLoc(),
4654 "destination operands must be sequential");
4655 return false;
4656 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004657 case ARM::STRD: {
4658 // Rt2 must be Rt + 1.
4659 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4660 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4661 if (Rt2 != Rt + 1)
4662 return Error(Operands[3]->getStartLoc(),
4663 "source operands must be sequential");
4664 return false;
4665 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004666 case ARM::STRD_PRE:
4667 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004668 case ARM::STREXD: {
4669 // Rt2 must be Rt + 1.
4670 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4671 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4672 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004673 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004674 "source operands must be sequential");
4675 return false;
4676 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004677 case ARM::SBFX:
4678 case ARM::UBFX: {
4679 // width must be in range [1, 32-lsb]
4680 unsigned lsb = Inst.getOperand(2).getImm();
4681 unsigned widthm1 = Inst.getOperand(3).getImm();
4682 if (widthm1 >= 32 - lsb)
4683 return Error(Operands[5]->getStartLoc(),
4684 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004685 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004686 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004687 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004688 // If we're parsing Thumb2, the .w variant is available and handles
4689 // most cases that are normally illegal for a Thumb1 LDM
4690 // instruction. We'll make the transformation in processInstruction()
4691 // if necessary.
4692 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004693 // Thumb LDM instructions are writeback iff the base register is not
4694 // in the register list.
4695 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004696 bool hasWritebackToken =
4697 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4698 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004699 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004700 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004701 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4702 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004703 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004704 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004705 return Error(Operands[2]->getStartLoc(),
4706 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004707 // If we should not have writeback, there must not be a '!'. This is
4708 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004709 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004710 return Error(Operands[3]->getStartLoc(),
4711 "writeback operator '!' not allowed when base register "
4712 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004713
4714 break;
4715 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004716 case ARM::t2LDMIA_UPD: {
4717 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4718 return Error(Operands[4]->getStartLoc(),
4719 "writeback operator '!' not allowed when base register "
4720 "in register list");
4721 break;
4722 }
Jim Grosbach54026372011-11-10 23:17:11 +00004723 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4724 // so only issue a diagnostic for thumb1. The instructions will be
4725 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004726 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004727 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004728 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4729 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004730 return Error(Operands[2]->getStartLoc(),
4731 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004732 break;
4733 }
4734 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004735 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004736 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4737 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004738 return Error(Operands[2]->getStartLoc(),
4739 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004740 break;
4741 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004742 case ARM::tSTMIA_UPD: {
4743 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004744 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004745 return Error(Operands[4]->getStartLoc(),
4746 "registers must be in range r0-r7");
4747 break;
4748 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004749 }
4750
4751 return false;
4752}
4753
Jim Grosbach7636bf62011-12-02 00:35:16 +00004754static unsigned getRealVLDNOpcode(unsigned Opc) {
4755 switch(Opc) {
4756 default: assert(0 && "unexpected opcode!");
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004757 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4758 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4759 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4760 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4761 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
4762 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4763 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4764 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4765 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4766 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
4767 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4768 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4769 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4770 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4771 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4772 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004773 }
4774}
4775
Jim Grosbach83ec8772011-11-10 23:42:14 +00004776bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004777processInstruction(MCInst &Inst,
4778 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4779 switch (Inst.getOpcode()) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004780 // Handle NEON VLD1 complex aliases.
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004781 case ARM::VLD1LNdAsm_8:
4782 case ARM::VLD1LNdAsm_P8:
4783 case ARM::VLD1LNdAsm_I8:
4784 case ARM::VLD1LNdAsm_S8:
4785 case ARM::VLD1LNdAsm_U8:
4786 case ARM::VLD1LNdAsm_16:
4787 case ARM::VLD1LNdAsm_P16:
4788 case ARM::VLD1LNdAsm_I16:
4789 case ARM::VLD1LNdAsm_S16:
4790 case ARM::VLD1LNdAsm_U16:
4791 case ARM::VLD1LNdAsm_32:
4792 case ARM::VLD1LNdAsm_F:
4793 case ARM::VLD1LNdAsm_F32:
4794 case ARM::VLD1LNdAsm_I32:
4795 case ARM::VLD1LNdAsm_S32:
4796 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004797 MCInst TmpInst;
4798 // Shuffle the operands around so the lane index operand is in the
4799 // right place.
4800 TmpInst.setOpcode(getRealVLDNOpcode(Inst.getOpcode()));
4801 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4802 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4803 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4804 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
4805 TmpInst.addOperand(Inst.getOperand(1)); // lane
4806 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
4807 TmpInst.addOperand(Inst.getOperand(5));
4808 Inst = TmpInst;
4809 return true;
4810 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00004811 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00004812 case ARM::ASRr:
4813 case ARM::LSRr:
4814 case ARM::LSLr:
4815 case ARM::RORr: {
4816 ARM_AM::ShiftOpc ShiftTy;
4817 switch(Inst.getOpcode()) {
4818 default: llvm_unreachable("unexpected opcode!");
4819 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4820 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4821 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4822 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4823 }
4824 // A shift by zero is a plain MOVr, not a MOVsi.
4825 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4826 MCInst TmpInst;
4827 TmpInst.setOpcode(ARM::MOVsr);
4828 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4829 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4830 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4831 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4832 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4833 TmpInst.addOperand(Inst.getOperand(4));
4834 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4835 Inst = TmpInst;
4836 return true;
4837 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00004838 case ARM::ASRi:
4839 case ARM::LSRi:
4840 case ARM::LSLi:
4841 case ARM::RORi: {
4842 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004843 switch(Inst.getOpcode()) {
4844 default: llvm_unreachable("unexpected opcode!");
4845 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4846 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4847 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4848 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4849 }
4850 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00004851 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00004852 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4853 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004854 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004855 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004856 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4857 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004858 if (Opc == ARM::MOVsi)
4859 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004860 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4861 TmpInst.addOperand(Inst.getOperand(4));
4862 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4863 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004864 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004865 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00004866 case ARM::RRXi: {
4867 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4868 MCInst TmpInst;
4869 TmpInst.setOpcode(ARM::MOVsi);
4870 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4871 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4872 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4873 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4874 TmpInst.addOperand(Inst.getOperand(3));
4875 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4876 Inst = TmpInst;
4877 return true;
4878 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004879 case ARM::t2LDMIA_UPD: {
4880 // If this is a load of a single register, then we should use
4881 // a post-indexed LDR instruction instead, per the ARM ARM.
4882 if (Inst.getNumOperands() != 5)
4883 return false;
4884 MCInst TmpInst;
4885 TmpInst.setOpcode(ARM::t2LDR_POST);
4886 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4887 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4888 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4889 TmpInst.addOperand(MCOperand::CreateImm(4));
4890 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4891 TmpInst.addOperand(Inst.getOperand(3));
4892 Inst = TmpInst;
4893 return true;
4894 }
4895 case ARM::t2STMDB_UPD: {
4896 // If this is a store of a single register, then we should use
4897 // a pre-indexed STR instruction instead, per the ARM ARM.
4898 if (Inst.getNumOperands() != 5)
4899 return false;
4900 MCInst TmpInst;
4901 TmpInst.setOpcode(ARM::t2STR_PRE);
4902 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4903 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4904 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4905 TmpInst.addOperand(MCOperand::CreateImm(-4));
4906 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4907 TmpInst.addOperand(Inst.getOperand(3));
4908 Inst = TmpInst;
4909 return true;
4910 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004911 case ARM::LDMIA_UPD:
4912 // If this is a load of a single register via a 'pop', then we should use
4913 // a post-indexed LDR instruction instead, per the ARM ARM.
4914 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4915 Inst.getNumOperands() == 5) {
4916 MCInst TmpInst;
4917 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4918 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4919 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4920 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4921 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4922 TmpInst.addOperand(MCOperand::CreateImm(4));
4923 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4924 TmpInst.addOperand(Inst.getOperand(3));
4925 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004926 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004927 }
4928 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004929 case ARM::STMDB_UPD:
4930 // If this is a store of a single register via a 'push', then we should use
4931 // a pre-indexed STR instruction instead, per the ARM ARM.
4932 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4933 Inst.getNumOperands() == 5) {
4934 MCInst TmpInst;
4935 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4936 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4937 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4938 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4939 TmpInst.addOperand(MCOperand::CreateImm(-4));
4940 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4941 TmpInst.addOperand(Inst.getOperand(3));
4942 Inst = TmpInst;
4943 }
4944 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004945 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004946 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4947 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4948 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4949 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004950 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004951 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004952 return true;
4953 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004954 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004955 case ARM::tSUBi8:
4956 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4957 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4958 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4959 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004960 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004961 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004962 return true;
4963 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004964 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004965 case ARM::tB:
4966 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004967 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004968 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004969 return true;
4970 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004971 break;
4972 case ARM::t2B:
4973 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004974 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004975 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004976 return true;
4977 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004978 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004979 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004980 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004981 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004982 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004983 return true;
4984 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004985 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004986 case ARM::tBcc:
4987 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004988 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004989 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004990 return true;
4991 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004992 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004993 case ARM::tLDMIA: {
4994 // If the register list contains any high registers, or if the writeback
4995 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4996 // instead if we're in Thumb2. Otherwise, this should have generated
4997 // an error in validateInstruction().
4998 unsigned Rn = Inst.getOperand(0).getReg();
4999 bool hasWritebackToken =
5000 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5001 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5002 bool listContainsBase;
5003 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5004 (!listContainsBase && !hasWritebackToken) ||
5005 (listContainsBase && hasWritebackToken)) {
5006 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5007 assert (isThumbTwo());
5008 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5009 // If we're switching to the updating version, we need to insert
5010 // the writeback tied operand.
5011 if (hasWritebackToken)
5012 Inst.insert(Inst.begin(),
5013 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005014 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005015 }
5016 break;
5017 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005018 case ARM::tSTMIA_UPD: {
5019 // If the register list contains any high registers, we need to use
5020 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5021 // should have generated an error in validateInstruction().
5022 unsigned Rn = Inst.getOperand(0).getReg();
5023 bool listContainsBase;
5024 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5025 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5026 assert (isThumbTwo());
5027 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005028 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005029 }
5030 break;
5031 }
Jim Grosbach54026372011-11-10 23:17:11 +00005032 case ARM::tPOP: {
5033 bool listContainsBase;
5034 // If the register list contains any high registers, we need to use
5035 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5036 // should have generated an error in validateInstruction().
5037 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005038 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005039 assert (isThumbTwo());
5040 Inst.setOpcode(ARM::t2LDMIA_UPD);
5041 // Add the base register and writeback operands.
5042 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5043 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005044 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005045 }
5046 case ARM::tPUSH: {
5047 bool listContainsBase;
5048 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005049 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005050 assert (isThumbTwo());
5051 Inst.setOpcode(ARM::t2STMDB_UPD);
5052 // Add the base register and writeback operands.
5053 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5054 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005055 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005056 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005057 case ARM::t2MOVi: {
5058 // If we can use the 16-bit encoding and the user didn't explicitly
5059 // request the 32-bit variant, transform it here.
5060 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5061 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005062 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5063 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5064 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005065 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5066 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5067 // The operands aren't in the same order for tMOVi8...
5068 MCInst TmpInst;
5069 TmpInst.setOpcode(ARM::tMOVi8);
5070 TmpInst.addOperand(Inst.getOperand(0));
5071 TmpInst.addOperand(Inst.getOperand(4));
5072 TmpInst.addOperand(Inst.getOperand(1));
5073 TmpInst.addOperand(Inst.getOperand(2));
5074 TmpInst.addOperand(Inst.getOperand(3));
5075 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005076 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005077 }
5078 break;
5079 }
5080 case ARM::t2MOVr: {
5081 // If we can use the 16-bit encoding and the user didn't explicitly
5082 // request the 32-bit variant, transform it here.
5083 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5084 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5085 Inst.getOperand(2).getImm() == ARMCC::AL &&
5086 Inst.getOperand(4).getReg() == ARM::CPSR &&
5087 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5088 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5089 // The operands aren't the same for tMOV[S]r... (no cc_out)
5090 MCInst TmpInst;
5091 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5092 TmpInst.addOperand(Inst.getOperand(0));
5093 TmpInst.addOperand(Inst.getOperand(1));
5094 TmpInst.addOperand(Inst.getOperand(2));
5095 TmpInst.addOperand(Inst.getOperand(3));
5096 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005097 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005098 }
5099 break;
5100 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005101 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005102 case ARM::t2SXTB:
5103 case ARM::t2UXTH:
5104 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005105 // If we can use the 16-bit encoding and the user didn't explicitly
5106 // request the 32-bit variant, transform it here.
5107 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5108 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5109 Inst.getOperand(2).getImm() == 0 &&
5110 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5111 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005112 unsigned NewOpc;
5113 switch (Inst.getOpcode()) {
5114 default: llvm_unreachable("Illegal opcode!");
5115 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5116 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5117 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5118 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5119 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005120 // The operands aren't the same for thumb1 (no rotate operand).
5121 MCInst TmpInst;
5122 TmpInst.setOpcode(NewOpc);
5123 TmpInst.addOperand(Inst.getOperand(0));
5124 TmpInst.addOperand(Inst.getOperand(1));
5125 TmpInst.addOperand(Inst.getOperand(3));
5126 TmpInst.addOperand(Inst.getOperand(4));
5127 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005128 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005129 }
5130 break;
5131 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005132 case ARM::t2IT: {
5133 // The mask bits for all but the first condition are represented as
5134 // the low bit of the condition code value implies 't'. We currently
5135 // always have 1 implies 't', so XOR toggle the bits if the low bit
5136 // of the condition code is zero. The encoding also expects the low
5137 // bit of the condition to be encoded as bit 4 of the mask operand,
5138 // so mask that in if needed
5139 MCOperand &MO = Inst.getOperand(1);
5140 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005141 unsigned OrigMask = Mask;
5142 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005143 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005144 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5145 for (unsigned i = 3; i != TZ; --i)
5146 Mask ^= 1 << i;
5147 } else
5148 Mask |= 0x10;
5149 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005150
5151 // Set up the IT block state according to the IT instruction we just
5152 // matched.
5153 assert(!inITBlock() && "nested IT blocks?!");
5154 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5155 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5156 ITState.CurPosition = 0;
5157 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005158 break;
5159 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005160 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005161 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005162}
5163
Jim Grosbach47a0d522011-08-16 20:45:50 +00005164unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5165 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5166 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005167 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005168 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005169 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5170 assert(MCID.hasOptionalDef() &&
5171 "optionally flag setting instruction missing optional def operand");
5172 assert(MCID.NumOperands == Inst.getNumOperands() &&
5173 "operand count mismatch!");
5174 // Find the optional-def operand (cc_out).
5175 unsigned OpNo;
5176 for (OpNo = 0;
5177 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5178 ++OpNo)
5179 ;
5180 // If we're parsing Thumb1, reject it completely.
5181 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5182 return Match_MnemonicFail;
5183 // If we're parsing Thumb2, which form is legal depends on whether we're
5184 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005185 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5186 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005187 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005188 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5189 inITBlock())
5190 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005191 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005192 // Some high-register supporting Thumb1 encodings only allow both registers
5193 // to be from r0-r7 when in Thumb2.
5194 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5195 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5196 isARMLowRegister(Inst.getOperand(2).getReg()))
5197 return Match_RequiresThumb2;
5198 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005199 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005200 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5201 isARMLowRegister(Inst.getOperand(1).getReg()))
5202 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005203 return Match_Success;
5204}
5205
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005206bool ARMAsmParser::
5207MatchAndEmitInstruction(SMLoc IDLoc,
5208 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5209 MCStreamer &Out) {
5210 MCInst Inst;
5211 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005212 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005213 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005214 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005215 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005216 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005217 // Context sensitive operand constraints aren't handled by the matcher,
5218 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005219 if (validateInstruction(Inst, Operands)) {
5220 // Still progress the IT block, otherwise one wrong condition causes
5221 // nasty cascading errors.
5222 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005223 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005224 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005225
Jim Grosbachf8fce712011-08-11 17:35:48 +00005226 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005227 // encoding is selected. Loop on it while changes happen so the
5228 // individual transformations can chain off each other. E.g.,
5229 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5230 while (processInstruction(Inst, Operands))
5231 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005232
Jim Grosbacha1109882011-09-02 23:22:08 +00005233 // Only move forward at the very end so that everything in validate
5234 // and process gets a consistent answer about whether we're in an IT
5235 // block.
5236 forwardITPosition();
5237
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005238 Out.EmitInstruction(Inst);
5239 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005240 case Match_MissingFeature:
5241 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5242 return true;
5243 case Match_InvalidOperand: {
5244 SMLoc ErrorLoc = IDLoc;
5245 if (ErrorInfo != ~0U) {
5246 if (ErrorInfo >= Operands.size())
5247 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005248
Chris Lattnere73d4f82010-10-28 21:41:58 +00005249 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5250 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5251 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005252
Chris Lattnere73d4f82010-10-28 21:41:58 +00005253 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005254 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005255 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005256 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005257 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005258 // The converter function will have already emited a diagnostic.
5259 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005260 case Match_RequiresNotITBlock:
5261 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005262 case Match_RequiresITBlock:
5263 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005264 case Match_RequiresV6:
5265 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5266 case Match_RequiresThumb2:
5267 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005268 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005269
Eric Christopherc223e2b2010-10-29 09:26:59 +00005270 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005271 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005272}
5273
Jim Grosbach1355cf12011-07-26 17:10:22 +00005274/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005275bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5276 StringRef IDVal = DirectiveID.getIdentifier();
5277 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005278 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005279 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005280 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005281 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005282 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005283 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005284 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005285 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005286 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005287 return true;
5288}
5289
Jim Grosbach1355cf12011-07-26 17:10:22 +00005290/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005291/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005292bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5294 for (;;) {
5295 const MCExpr *Value;
5296 if (getParser().ParseExpression(Value))
5297 return true;
5298
Chris Lattneraaec2052010-01-19 19:46:13 +00005299 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005300
5301 if (getLexer().is(AsmToken::EndOfStatement))
5302 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005303
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005304 // FIXME: Improve diagnostic.
5305 if (getLexer().isNot(AsmToken::Comma))
5306 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005307 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005308 }
5309 }
5310
Sean Callananb9a25b72010-01-19 20:27:46 +00005311 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005312 return false;
5313}
5314
Jim Grosbach1355cf12011-07-26 17:10:22 +00005315/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005316/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005317bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005318 if (getLexer().isNot(AsmToken::EndOfStatement))
5319 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005320 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005321
5322 // TODO: set thumb mode
5323 // TODO: tell the MC streamer the mode
5324 // getParser().getStreamer().Emit???();
5325 return false;
5326}
5327
Jim Grosbach1355cf12011-07-26 17:10:22 +00005328/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005329/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005330bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005331 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5332 bool isMachO = MAI.hasSubsectionsViaSymbols();
5333 StringRef Name;
5334
5335 // Darwin asm has function name after .thumb_func direction
5336 // ELF doesn't
5337 if (isMachO) {
5338 const AsmToken &Tok = Parser.getTok();
5339 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5340 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005341 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005342 Parser.Lex(); // Consume the identifier token.
5343 }
5344
Jim Grosbachd475f862011-11-10 20:48:53 +00005345 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005346 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005347 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005348
Rafael Espindola64695402011-05-16 16:17:21 +00005349 // FIXME: assuming function name will be the line following .thumb_func
5350 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005351 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005352 }
5353
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005354 // Mark symbol as a thumb symbol.
5355 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5356 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005357 return false;
5358}
5359
Jim Grosbach1355cf12011-07-26 17:10:22 +00005360/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005361/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005362bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005363 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005364 if (Tok.isNot(AsmToken::Identifier))
5365 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005366 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005367 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005368 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005369 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005370 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005371 else
5372 return Error(L, "unrecognized syntax mode in .syntax directive");
5373
5374 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005375 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005376 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005377
5378 // TODO tell the MC streamer the mode
5379 // getParser().getStreamer().Emit???();
5380 return false;
5381}
5382
Jim Grosbach1355cf12011-07-26 17:10:22 +00005383/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005384/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005385bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005386 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005387 if (Tok.isNot(AsmToken::Integer))
5388 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005389 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005390 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005391 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005392 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005393 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005394 else
5395 return Error(L, "invalid operand to .code directive");
5396
5397 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005398 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005399 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005400
Evan Cheng32869202011-07-08 22:36:29 +00005401 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005402 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005403 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005404 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005405 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005406 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005407 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005408 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005409 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005410
Kevin Enderby515d5092009-10-15 20:48:48 +00005411 return false;
5412}
5413
Sean Callanan90b70972010-04-07 20:29:34 +00005414extern "C" void LLVMInitializeARMAsmLexer();
5415
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005416/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005417extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005418 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5419 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005420 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005421}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005422
Chris Lattner0692ee62010-09-06 19:11:01 +00005423#define GET_REGISTER_MATCHER
5424#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005425#include "ARMGenAsmMatcher.inc"