blob: 6974b1148a95bd8cb5dd03d89e3e6fdccc1b299e [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
Evan Cheng94b95502011-07-26 00:24:13 +000042class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000043 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000044 MCAsmParser &Parser;
45
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000046 struct {
47 ARMCC::CondCodes Cond; // Condition for IT block.
48 unsigned Mask:4; // Condition mask for instructions.
49 // Starting at first 1 (from lsb).
50 // '1' condition as indicated in IT.
51 // '0' inverse of condition (else).
52 // Count of instructions in IT block is
53 // 4 - trailingzeroes(mask)
54
55 bool FirstCond; // Explicit flag for when we're parsing the
56 // First instruction in the IT block. It's
57 // implied in the mask, so needs special
58 // handling.
59
60 unsigned CurPosition; // Current position in parsing of IT
61 // block. In range [0,3]. Initialized
62 // according to count of instructions in block.
63 // ~0U if no active IT block.
64 } ITState;
65 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000066 void forwardITPosition() {
67 if (!inITBlock()) return;
68 // Move to the next instruction in the IT block, if there is one. If not,
69 // mark the block as done.
70 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
71 if (++ITState.CurPosition == 5 - TZ)
72 ITState.CurPosition = ~0U; // Done with the IT block after this.
73 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000074
75
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000076 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
78
79 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000080 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
81
Jim Grosbach1355cf12011-07-26 17:10:22 +000082 int tryParseRegister();
83 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000084 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000085 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000086 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
88 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000089 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
90 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000091 bool parseDirectiveWord(unsigned Size, SMLoc L);
92 bool parseDirectiveThumb(SMLoc L);
93 bool parseDirectiveThumbFunc(SMLoc L);
94 bool parseDirectiveCode(SMLoc L);
95 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000096
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000098 bool &CarrySetting, unsigned &ProcessorIMod,
99 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000101 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000102
Evan Chengebdeeab2011-07-08 01:53:10 +0000103 bool isThumb() const {
104 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000105 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000110 bool isThumbTwo() const {
111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
112 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000113 bool hasV6Ops() const {
114 return STI.getFeatureBits() & ARM::HasV6Ops;
115 }
James Molloyacad68d2011-09-28 14:21:38 +0000116 bool hasV7Ops() const {
117 return STI.getFeatureBits() & ARM::HasV7Ops;
118 }
Evan Cheng32869202011-07-08 22:36:29 +0000119 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000120 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
121 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000122 }
James Molloyacad68d2011-09-28 14:21:38 +0000123 bool isMClass() const {
124 return STI.getFeatureBits() & ARM::FeatureMClass;
125 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000126
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000127 /// @name Auto-generated Match Functions
128 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000129
Chris Lattner0692ee62010-09-06 19:11:01 +0000130#define GET_ASSEMBLER_HEADER
131#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000132
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133 /// }
134
Jim Grosbach89df9962011-08-26 21:43:41 +0000135 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000136 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000137 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000140 OperandMatchResultTy parseCoprocOptionOperand(
141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000142 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000148 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
149 StringRef Op, int Low, int High);
150 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
151 return parsePKHImm(O, "lsl", 0, 31);
152 }
153 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "asr", 1, 32);
155 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000156 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000157 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000158 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000159 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000160 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000161 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000162 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000163 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000200 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000204 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000208
209 bool validateInstruction(MCInst &Inst,
210 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000211 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000212 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000213 bool shouldOmitCCOutOperand(StringRef Mnemonic,
214 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000215
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000216public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000217 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000218 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000219 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000220 Match_RequiresV6,
221 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000222 };
223
Evan Chengffc0e732011-07-09 05:47:46 +0000224 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000225 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000226 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000227
Evan Chengebdeeab2011-07-08 01:53:10 +0000228 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230
231 // Not in an ITBlock to start with.
232 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000233 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 // Implementation of the MCTargetAsmParser interface:
236 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
237 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000238 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 bool ParseDirective(AsmToken DirectiveID);
240
Jim Grosbach47a0d522011-08-16 20:45:50 +0000241 unsigned checkTargetMatchPredicate(MCInst &Inst);
242
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool MatchAndEmitInstruction(SMLoc IDLoc,
244 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
245 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000246};
Jim Grosbach16c74252010-10-29 14:46:02 +0000247} // end anonymous namespace
248
Chris Lattner3a697562010-10-28 17:20:03 +0000249namespace {
250
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000251/// ARMOperand - Instances of this class represent a parsed ARM machine
252/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000253class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000254 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000255 k_CondCode,
256 k_CCOut,
257 k_ITCondMask,
258 k_CoprocNum,
259 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000260 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000261 k_Immediate,
262 k_FPImmediate,
263 k_MemBarrierOpt,
264 k_Memory,
265 k_PostIndexRegister,
266 k_MSRMask,
267 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000268 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000269 k_Register,
270 k_RegisterList,
271 k_DPRRegisterList,
272 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000273 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000274 k_ShiftedRegister,
275 k_ShiftedImmediate,
276 k_ShifterImmediate,
277 k_RotateImmediate,
278 k_BitfieldDescriptor,
279 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000280 } Kind;
281
Sean Callanan76264762010-04-02 22:27:05 +0000282 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000283 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000284
285 union {
286 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000287 ARMCC::CondCodes Val;
288 } CC;
289
290 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000291 unsigned Val;
292 } Cop;
293
294 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000295 unsigned Val;
296 } CoprocOption;
297
298 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000299 unsigned Mask:4;
300 } ITMask;
301
302 struct {
303 ARM_MB::MemBOpt Val;
304 } MBOpt;
305
306 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000307 ARM_PROC::IFlags Val;
308 } IFlags;
309
310 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000311 unsigned Val;
312 } MMask;
313
314 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000315 const char *Data;
316 unsigned Length;
317 } Tok;
318
319 struct {
320 unsigned RegNum;
321 } Reg;
322
Jim Grosbach862019c2011-10-18 23:02:30 +0000323 // A vector register list is a sequential list of 1 to 4 registers.
324 struct {
325 unsigned RegNum;
326 unsigned Count;
327 } VectorList;
328
Bill Wendling8155e5b2010-11-06 22:19:43 +0000329 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000330 unsigned Val;
331 } VectorIndex;
332
333 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000334 const MCExpr *Val;
335 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000336
Jim Grosbach9d390362011-10-03 23:38:36 +0000337 struct {
338 unsigned Val; // encoded 8-bit representation
339 } FPImm;
340
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000341 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000342 struct {
343 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000344 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
345 // was specified.
346 const MCConstantExpr *OffsetImm; // Offset immediate value
347 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
348 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000349 unsigned ShiftImm; // shift for OffsetReg.
350 unsigned Alignment; // 0 = no alignment specified
351 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000352 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000353 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000354
355 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000356 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000357 bool isAdd;
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000360 } PostIdxReg;
361
362 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000363 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000364 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000365 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000366 struct {
367 ARM_AM::ShiftOpc ShiftTy;
368 unsigned SrcReg;
369 unsigned ShiftReg;
370 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000371 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000376 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000377 struct {
378 unsigned Imm;
379 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000380 struct {
381 unsigned LSB;
382 unsigned Width;
383 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000384 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000385
Bill Wendling146018f2010-11-06 21:42:12 +0000386 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
387public:
Sean Callanan76264762010-04-02 22:27:05 +0000388 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
389 Kind = o.Kind;
390 StartLoc = o.StartLoc;
391 EndLoc = o.EndLoc;
392 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000394 CC = o.CC;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000397 ITMask = o.ITMask;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000400 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_CCOut:
403 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Reg = o.Reg;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_RegisterList:
407 case k_DPRRegisterList:
408 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000409 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000410 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000411 case k_VectorList:
412 VectorList = o.VectorList;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_CoprocNum:
415 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000416 Cop = o.Cop;
417 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000418 case k_CoprocOption:
419 CoprocOption = o.CoprocOption;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000422 Imm = o.Imm;
423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000425 FPImm = o.FPImm;
426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000428 MBOpt = o.MBOpt;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000431 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000434 PostIdxReg = o.PostIdxReg;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000437 MMask = o.MMask;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000440 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000443 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000446 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000449 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000452 RotImm = o.RotImm;
453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000455 Bitfield = o.Bitfield;
456 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
Sean Callanan76264762010-04-02 22:27:05 +0000460 }
461 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000462
Sean Callanan76264762010-04-02 22:27:05 +0000463 /// getStartLoc - Get the location of the first token of this operand.
464 SMLoc getStartLoc() const { return StartLoc; }
465 /// getEndLoc - Get the location of the last token of this operand.
466 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000467
Daniel Dunbar8462b302010-08-11 06:36:53 +0000468 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000469 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000470 return CC.Val;
471 }
472
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000473 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000474 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000475 return Cop.Val;
476 }
477
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000478 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000479 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000480 return StringRef(Tok.Data, Tok.Length);
481 }
482
483 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000484 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000485 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 }
487
Bill Wendling5fa22a12010-11-09 23:28:44 +0000488 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000489 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
490 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000491 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000492 }
493
Kevin Enderbycfe07242009-10-13 22:19:02 +0000494 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000495 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000496 return Imm.Val;
497 }
498
Jim Grosbach9d390362011-10-03 23:38:36 +0000499 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000501 return FPImm.Val;
502 }
503
Jim Grosbach460a9052011-10-07 23:56:00 +0000504 unsigned getVectorIndex() const {
505 assert(Kind == k_VectorIndex && "Invalid access!");
506 return VectorIndex.Val;
507 }
508
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000509 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000510 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000511 return MBOpt.Val;
512 }
513
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000514 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000515 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000516 return IFlags.Val;
517 }
518
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000519 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000520 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000521 return MMask.Val;
522 }
523
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 bool isCoprocNum() const { return Kind == k_CoprocNum; }
525 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000526 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 bool isCondCode() const { return Kind == k_CondCode; }
528 bool isCCOut() const { return Kind == k_CCOut; }
529 bool isITMask() const { return Kind == k_ITCondMask; }
530 bool isITCondCode() const { return Kind == k_CondCode; }
531 bool isImm() const { return Kind == k_Immediate; }
532 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000533 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000535 return false;
536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
537 if (!CE) return false;
538 int64_t Value = CE->getValue();
539 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
540 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000541 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +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 >= 0 && Value <= 1020;
548 }
549 bool isImm0_508s4() 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 <= 508;
556 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000557 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +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 >= 0 && Value < 256;
564 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000565 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +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 < 8;
572 }
573 bool isImm0_15() 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 < 16;
580 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000581 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +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 < 32;
588 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000589 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +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 < 17;
596 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000597 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +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 < 33;
604 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000605 bool isImm0_32() const {
606 if (Kind != k_Immediate)
607 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 Grosbachfff76ee2011-07-13 20:10:10 +0000613 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000615 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 < 65536;
620 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000621 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 // If it's not a constant expression, it'll generate a fixup and be
626 // handled later.
627 if (!CE) return true;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 65536;
630 }
Jim Grosbached838482011-07-26 16:24:27 +0000631 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000633 return false;
634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
635 if (!CE) return false;
636 int64_t Value = CE->getValue();
637 return Value >= 0 && Value <= 0xffffff;
638 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000639 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51: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 < 33;
646 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000647 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +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 < 32;
654 }
655 bool isPKHASRImm() 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 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000663 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return ARM_AM::getSOImmVal(Value) != -1;
670 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000671 bool isARMSOImmNot() const {
672 if (Kind != k_Immediate)
673 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 Grosbach6b8f1e32011-06-27 23:54:06 +0000679 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000680 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000681 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::getT2SOImmVal(Value) != -1;
686 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000687 bool isT2SOImmNot() const {
688 if (Kind != k_Immediate)
689 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 Grosbachc27d4f92011-07-22 17:44:50 +0000695 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000696 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value == 1 || Value == 0;
702 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000703 bool isReg() const { return Kind == k_Register; }
704 bool isRegList() const { return Kind == k_RegisterList; }
705 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
706 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
707 bool isToken() const { return Kind == k_Token; }
708 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
709 bool isMemory() const { return Kind == k_Memory; }
710 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
711 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
712 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
713 bool isRotImm() const { return Kind == k_RotateImmediate; }
714 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
715 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000716 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000717 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000718 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000719 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000720 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000721 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000722 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000723 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
724 (alignOK || Memory.Alignment == 0);
725 }
726 bool isAlignedMemory() const {
727 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000728 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000729 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000730 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000731 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000732 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000733 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000734 if (!Memory.OffsetImm) return true;
735 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000736 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000737 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000738 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000739 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000740 return false;
741 // Immediate offset in range [-4095, 4095].
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 int64_t Val = CE->getValue();
745 return Val > -4096 && Val < 4096;
746 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000747 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000748 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000749 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000751 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000752 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000753 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000754 if (!Memory.OffsetImm) return true;
755 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000756 return Val > -256 && Val < 256;
757 }
758 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000760 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000762 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
763 // Immediate offset in range [-255, 255].
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000767 // Special case, #-0 is INT32_MIN.
768 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000769 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000770 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000771 // If we have an immediate that's not a constant, treat it as a label
772 // reference needing a fixup. If it is a constant, it's something else
773 // and we reject it.
774 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
775 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000776 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000777 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000778 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000779 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000780 if (!Memory.OffsetImm) return true;
781 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000782 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000783 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000784 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000785 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
791 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
794 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000795 return false;
796 return true;
797 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000798 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000799 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000800 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000801 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000802 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000803 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
805 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000806 return false;
807 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000809 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000811 return false;
812 return true;
813 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000814 bool isMemThumbRR() const {
815 // Thumb reg+reg addressing is simple. Just two registers, a base and
816 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000817 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000819 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000820 return isARMLowRegister(Memory.BaseRegNum) &&
821 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000822 }
823 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000825 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000826 return false;
827 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000828 if (!Memory.OffsetImm) return true;
829 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000830 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
831 }
Jim Grosbach38466302011-08-19 18:55:51 +0000832 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000833 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000835 return false;
836 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000839 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
840 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000841 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000842 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000843 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000844 return false;
845 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000846 if (!Memory.OffsetImm) return true;
847 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000848 return Val >= 0 && Val <= 31;
849 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000850 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000851 if (!isMemory() || Memory.OffsetRegNum != 0 ||
852 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000853 return false;
854 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000857 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000858 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000859 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000865 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000867 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000873 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000877 return false;
878 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000881 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000883 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000885 return false;
886 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000889 return Val >= 0 && Val < 256;
890 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000891 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000893 return false;
894 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000897 return Val > -256 && Val < 0;
898 }
899 bool isMemUImm12Offset() 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 [0, 4095].
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 >= 0 && Val < 4096);
906 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000908 // If we have an immediate that's not a constant, treat it as a label
909 // reference needing a fixup. If it is a constant, it's something else
910 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000911 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000912 return true;
913
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000915 return false;
916 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000919 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000920 }
921 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000927 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000929 bool isPostIdxImm8s4() const {
930 if (Kind != k_Immediate)
931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
935 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
936 (Val == INT32_MIN);
937 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000938
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000939 bool isMSRMask() const { return Kind == k_MSRMask; }
940 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000941
Jim Grosbach0e387b22011-10-17 22:26:03 +0000942 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000943 bool isVecListOneD() const {
944 if (Kind != k_VectorList) return false;
945 return VectorList.Count == 1;
946 }
947
Jim Grosbach280dfad2011-10-21 18:54:25 +0000948 bool isVecListTwoD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 2;
951 }
952
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000953 bool isVecListThreeD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 3;
956 }
957
Jim Grosbachb6310312011-10-21 20:35:01 +0000958 bool isVecListFourD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 4;
961 }
962
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000963 bool isVecListTwoQ() const {
964 if (Kind != k_VectorList) return false;
965 //FIXME: We haven't taught the parser to handle by-two register lists
966 // yet, so don't pretend to know one.
967 return VectorList.Count == 2 && false;
968 }
969
Jim Grosbach460a9052011-10-07 23:56:00 +0000970 bool isVectorIndex8() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 8;
973 }
974 bool isVectorIndex16() const {
975 if (Kind != k_VectorIndex) return false;
976 return VectorIndex.Val < 4;
977 }
978 bool isVectorIndex32() const {
979 if (Kind != k_VectorIndex) return false;
980 return VectorIndex.Val < 2;
981 }
982
Jim Grosbach0e387b22011-10-17 22:26:03 +0000983 bool isNEONi8splat() const {
984 if (Kind != k_Immediate)
985 return false;
986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
987 // Must be a constant.
988 if (!CE) return false;
989 int64_t Value = CE->getValue();
990 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
991 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000992 return Value >= 0 && Value < 256;
993 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000994
Jim Grosbachea461102011-10-17 23:09:09 +0000995 bool isNEONi16splat() const {
996 if (Kind != k_Immediate)
997 return false;
998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
999 // Must be a constant.
1000 if (!CE) return false;
1001 int64_t Value = CE->getValue();
1002 // i16 value in the range [0,255] or [0x0100, 0xff00]
1003 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1004 }
1005
Jim Grosbach6248a542011-10-18 00:22:00 +00001006 bool isNEONi32splat() 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 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1014 return (Value >= 0 && Value < 256) ||
1015 (Value >= 0x0100 && Value <= 0xff00) ||
1016 (Value >= 0x010000 && Value <= 0xff0000) ||
1017 (Value >= 0x01000000 && Value <= 0xff000000);
1018 }
1019
1020 bool isNEONi32vmov() const {
1021 if (Kind != k_Immediate)
1022 return false;
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 // Must be a constant.
1025 if (!CE) return false;
1026 int64_t Value = CE->getValue();
1027 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1028 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000) ||
1033 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1034 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1035 }
1036
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001037 bool isNEONi64splat() const {
1038 if (Kind != k_Immediate)
1039 return false;
1040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 // Must be a constant.
1042 if (!CE) return false;
1043 uint64_t Value = CE->getValue();
1044 // i64 value with each byte being either 0 or 0xff.
1045 for (unsigned i = 0; i < 8; ++i)
1046 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1047 return true;
1048 }
1049
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001050 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001051 // Add as immediates when possible. Null MCExpr = 0.
1052 if (Expr == 0)
1053 Inst.addOperand(MCOperand::CreateImm(0));
1054 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001055 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1056 else
1057 Inst.addOperand(MCOperand::CreateExpr(Expr));
1058 }
1059
Daniel Dunbar8462b302010-08-11 06:36:53 +00001060 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001061 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001062 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001063 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1064 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001065 }
1066
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001067 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1070 }
1071
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001072 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1075 }
1076
1077 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1080 }
1081
Jim Grosbach89df9962011-08-26 21:43:41 +00001082 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1085 }
1086
1087 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1090 }
1091
Jim Grosbachd67641b2010-12-06 18:21:12 +00001092 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateReg(getReg()));
1095 }
1096
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001097 void addRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateReg(getReg()));
1100 }
1101
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001102 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001103 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001104 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1105 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001107 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001108 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001109 }
1110
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001111 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001112 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001113 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1114 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001115 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001116 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001117 }
1118
Jim Grosbach580f4a92011-07-25 22:20:28 +00001119 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001120 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001121 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1122 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001123 }
1124
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001125 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001126 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001127 const SmallVectorImpl<unsigned> &RegList = getRegList();
1128 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001129 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1130 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001131 }
1132
Bill Wendling0f630752010-11-17 04:32:08 +00001133 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1134 addRegListOperands(Inst, N);
1135 }
1136
1137 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1138 addRegListOperands(Inst, N);
1139 }
1140
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001141 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1142 assert(N == 1 && "Invalid number of operands!");
1143 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1144 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1145 }
1146
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001147 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 // Munge the lsb/width into a bitfield mask.
1150 unsigned lsb = Bitfield.LSB;
1151 unsigned width = Bitfield.Width;
1152 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1153 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1154 (32 - (lsb + width)));
1155 Inst.addOperand(MCOperand::CreateImm(Mask));
1156 }
1157
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001158 void addImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 addExpr(Inst, getImm());
1161 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001162
Jim Grosbach9d390362011-10-03 23:38:36 +00001163 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
1165 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1166 }
1167
Jim Grosbacha77295d2011-09-08 22:07:06 +00001168 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // FIXME: We really want to scale the value here, but the LDRD/STRD
1171 // instruction don't encode operands that way yet.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1174 }
1175
Jim Grosbach72f39f82011-08-24 21:22:15 +00001176 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 // The immediate is scaled by four in the encoding and is stored
1179 // in the MCInst as such. Lop off the low two bits here.
1180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1181 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1182 }
1183
1184 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 // The immediate is scaled by four in the encoding and is stored
1187 // in the MCInst as such. Lop off the low two bits here.
1188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1189 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1190 }
1191
Jim Grosbachf4943352011-07-25 23:09:14 +00001192 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 // The constant encodes as the immediate-1, and we store in the instruction
1195 // the bits as encoded, so subtract off one here.
1196 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1197 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1198 }
1199
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001200 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
1202 // The constant encodes as the immediate-1, and we store in the instruction
1203 // the bits as encoded, so subtract off one here.
1204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1205 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1206 }
1207
Jim Grosbach70939ee2011-08-17 21:51:27 +00001208 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
1210 // The constant encodes as the immediate, except for 32, which encodes as
1211 // zero.
1212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1213 unsigned Imm = CE->getValue();
1214 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1215 }
1216
Jim Grosbachf6c05252011-07-21 17:23:04 +00001217 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1220 // the instruction as well.
1221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1222 int Val = CE->getValue();
1223 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1224 }
1225
Jim Grosbach89a63372011-10-28 22:36:30 +00001226 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 // The operand is actually a t2_so_imm, but we have its bitwise
1229 // negation in the assembly source, so twiddle it here.
1230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1231 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1232 }
1233
Jim Grosbache70ec842011-10-28 22:50:54 +00001234 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 // The operand is actually a so_imm, but we have its bitwise
1237 // negation in the assembly source, so twiddle it here.
1238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1239 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1240 }
1241
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001242 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
1244 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1245 }
1246
Jim Grosbach7ce05792011-08-03 23:50:40 +00001247 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001249 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001250 }
1251
Jim Grosbach57dcb852011-10-11 17:29:55 +00001252 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 2 && "Invalid number of operands!");
1254 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1255 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1256 }
1257
Jim Grosbach7ce05792011-08-03 23:50:40 +00001258 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1259 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001260 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1261 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001262 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1263 // Special case for #-0
1264 if (Val == INT32_MIN) Val = 0;
1265 if (Val < 0) Val = -Val;
1266 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1267 } else {
1268 // For register offset, we encode the shift type and negation flag
1269 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001270 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1271 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001272 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001273 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1274 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001275 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001276 }
1277
Jim Grosbach039c2e12011-08-04 23:01:30 +00001278 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1279 assert(N == 2 && "Invalid number of operands!");
1280 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1281 assert(CE && "non-constant AM2OffsetImm operand!");
1282 int32_t Val = CE->getValue();
1283 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1284 // Special case for #-0
1285 if (Val == INT32_MIN) Val = 0;
1286 if (Val < 0) Val = -Val;
1287 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1288 Inst.addOperand(MCOperand::CreateReg(0));
1289 Inst.addOperand(MCOperand::CreateImm(Val));
1290 }
1291
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001292 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1293 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001294 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1295 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001296 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1297 // Special case for #-0
1298 if (Val == INT32_MIN) Val = 0;
1299 if (Val < 0) Val = -Val;
1300 Val = ARM_AM::getAM3Opc(AddSub, Val);
1301 } else {
1302 // For register offset, we encode the shift type and negation flag
1303 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001304 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001305 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001306 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1307 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001308 Inst.addOperand(MCOperand::CreateImm(Val));
1309 }
1310
1311 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1312 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001313 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001314 int32_t Val =
1315 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1316 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1317 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001318 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001319 }
1320
1321 // Constant offset.
1322 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1323 int32_t Val = CE->getValue();
1324 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1325 // Special case for #-0
1326 if (Val == INT32_MIN) Val = 0;
1327 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001328 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001329 Inst.addOperand(MCOperand::CreateReg(0));
1330 Inst.addOperand(MCOperand::CreateImm(Val));
1331 }
1332
Jim Grosbach7ce05792011-08-03 23:50:40 +00001333 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001335 // If we have an immediate that's not a constant, treat it as a label
1336 // reference needing a fixup. If it is a constant, it's something else
1337 // and we reject it.
1338 if (isImm()) {
1339 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1340 Inst.addOperand(MCOperand::CreateImm(0));
1341 return;
1342 }
1343
Jim Grosbach7ce05792011-08-03 23:50:40 +00001344 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001345 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001346 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1347 // Special case for #-0
1348 if (Val == INT32_MIN) Val = 0;
1349 if (Val < 0) Val = -Val;
1350 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001351 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001352 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001353 }
1354
Jim Grosbacha77295d2011-09-08 22:07:06 +00001355 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1356 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001357 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1358 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001359 Inst.addOperand(MCOperand::CreateImm(Val));
1360 }
1361
Jim Grosbachb6aed502011-09-09 18:37:27 +00001362 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1363 assert(N == 2 && "Invalid number of operands!");
1364 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001365 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001367 Inst.addOperand(MCOperand::CreateImm(Val));
1368 }
1369
Jim Grosbach7ce05792011-08-03 23:50:40 +00001370 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001372 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1373 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001374 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001375 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001376
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001377 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1378 addMemImm8OffsetOperands(Inst, N);
1379 }
1380
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001381 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001382 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001383 }
1384
1385 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 2 && "Invalid number of operands!");
1387 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001388 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001389 addExpr(Inst, getImm());
1390 Inst.addOperand(MCOperand::CreateImm(0));
1391 return;
1392 }
1393
1394 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001395 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1396 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
1398 }
1399
Jim Grosbach7ce05792011-08-03 23:50:40 +00001400 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001402 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001403 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001404 addExpr(Inst, getImm());
1405 Inst.addOperand(MCOperand::CreateImm(0));
1406 return;
1407 }
1408
1409 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001410 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001412 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001413 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001414
Jim Grosbach7f739be2011-09-19 22:21:13 +00001415 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001417 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1418 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001419 }
1420
1421 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001423 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1424 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001425 }
1426
Jim Grosbach7ce05792011-08-03 23:50:40 +00001427 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1428 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001429 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1430 Memory.ShiftImm, Memory.ShiftType);
1431 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1432 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001433 Inst.addOperand(MCOperand::CreateImm(Val));
1434 }
1435
Jim Grosbachab899c12011-09-07 23:10:15 +00001436 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001438 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1439 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1440 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001441 }
1442
Jim Grosbach7ce05792011-08-03 23:50:40 +00001443 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001445 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1446 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001447 }
1448
Jim Grosbach60f91a32011-08-19 17:55:24 +00001449 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1450 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001451 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1452 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001453 Inst.addOperand(MCOperand::CreateImm(Val));
1454 }
1455
Jim Grosbach38466302011-08-19 18:55:51 +00001456 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1457 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001458 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1459 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001460 Inst.addOperand(MCOperand::CreateImm(Val));
1461 }
1462
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001463 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001465 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1466 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001467 Inst.addOperand(MCOperand::CreateImm(Val));
1468 }
1469
Jim Grosbachecd85892011-08-19 18:13:48 +00001470 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001472 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1473 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001474 Inst.addOperand(MCOperand::CreateImm(Val));
1475 }
1476
Jim Grosbach7ce05792011-08-03 23:50:40 +00001477 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 assert(CE && "non-constant post-idx-imm8 operand!");
1481 int Imm = CE->getValue();
1482 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001483 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001484 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1485 Inst.addOperand(MCOperand::CreateImm(Imm));
1486 }
1487
Jim Grosbach2bd01182011-10-11 21:55:36 +00001488 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 assert(CE && "non-constant post-idx-imm8s4 operand!");
1492 int Imm = CE->getValue();
1493 bool isAdd = Imm >= 0;
1494 if (Imm == INT32_MIN) Imm = 0;
1495 // Immediate is scaled by 4.
1496 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1497 Inst.addOperand(MCOperand::CreateImm(Imm));
1498 }
1499
Jim Grosbach7ce05792011-08-03 23:50:40 +00001500 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
1502 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001503 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1504 }
1505
1506 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 2 && "Invalid number of operands!");
1508 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1509 // The sign, shift type, and shift amount are encoded in a single operand
1510 // using the AM2 encoding helpers.
1511 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1512 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1513 PostIdxReg.ShiftTy);
1514 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001515 }
1516
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001517 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1520 }
1521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001522 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1525 }
1526
Jim Grosbach862019c2011-10-18 23:02:30 +00001527 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 1 && "Invalid number of operands!");
1529 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1530 }
1531
Jim Grosbach280dfad2011-10-21 18:54:25 +00001532 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 // Only the first register actually goes on the instruction. The rest
1535 // are implied by the opcode.
1536 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1537 }
1538
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001539 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // Only the first register actually goes on the instruction. The rest
1542 // are implied by the opcode.
1543 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1544 }
1545
Jim Grosbachb6310312011-10-21 20:35:01 +00001546 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
1548 // Only the first register actually goes on the instruction. The rest
1549 // are implied by the opcode.
1550 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1551 }
1552
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001553 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1554 assert(N == 1 && "Invalid number of operands!");
1555 // Only the first register actually goes on the instruction. The rest
1556 // are implied by the opcode.
1557 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1558 }
1559
Jim Grosbach460a9052011-10-07 23:56:00 +00001560 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1563 }
1564
1565 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1568 }
1569
1570 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1573 }
1574
Jim Grosbach0e387b22011-10-17 22:26:03 +00001575 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 // The immediate encodes the type of constant as well as the value.
1578 // Mask in that this is an i8 splat.
1579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1580 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1581 }
1582
Jim Grosbachea461102011-10-17 23:09:09 +00001583 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 // The immediate encodes the type of constant as well as the value.
1586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1587 unsigned Value = CE->getValue();
1588 if (Value >= 256)
1589 Value = (Value >> 8) | 0xa00;
1590 else
1591 Value |= 0x800;
1592 Inst.addOperand(MCOperand::CreateImm(Value));
1593 }
1594
Jim Grosbach6248a542011-10-18 00:22:00 +00001595 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1596 assert(N == 1 && "Invalid number of operands!");
1597 // The immediate encodes the type of constant as well as the value.
1598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1599 unsigned Value = CE->getValue();
1600 if (Value >= 256 && Value <= 0xff00)
1601 Value = (Value >> 8) | 0x200;
1602 else if (Value > 0xffff && Value <= 0xff0000)
1603 Value = (Value >> 16) | 0x400;
1604 else if (Value > 0xffffff)
1605 Value = (Value >> 24) | 0x600;
1606 Inst.addOperand(MCOperand::CreateImm(Value));
1607 }
1608
1609 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 // The immediate encodes the type of constant as well as the value.
1612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1613 unsigned Value = CE->getValue();
1614 if (Value >= 256 && Value <= 0xffff)
1615 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1616 else if (Value > 0xffff && Value <= 0xffffff)
1617 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1618 else if (Value > 0xffffff)
1619 Value = (Value >> 24) | 0x600;
1620 Inst.addOperand(MCOperand::CreateImm(Value));
1621 }
1622
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001623 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1624 assert(N == 1 && "Invalid number of operands!");
1625 // The immediate encodes the type of constant as well as the value.
1626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1627 uint64_t Value = CE->getValue();
1628 unsigned Imm = 0;
1629 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1630 Imm |= (Value & 1) << i;
1631 }
1632 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1633 }
1634
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001635 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001636
Jim Grosbach89df9962011-08-26 21:43:41 +00001637 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001638 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001639 Op->ITMask.Mask = Mask;
1640 Op->StartLoc = S;
1641 Op->EndLoc = S;
1642 return Op;
1643 }
1644
Chris Lattner3a697562010-10-28 17:20:03 +00001645 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001646 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001647 Op->CC.Val = CC;
1648 Op->StartLoc = S;
1649 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001650 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001651 }
1652
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001653 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001654 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001655 Op->Cop.Val = CopVal;
1656 Op->StartLoc = S;
1657 Op->EndLoc = S;
1658 return Op;
1659 }
1660
1661 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001662 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001663 Op->Cop.Val = CopVal;
1664 Op->StartLoc = S;
1665 Op->EndLoc = S;
1666 return Op;
1667 }
1668
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001669 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1670 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1671 Op->Cop.Val = Val;
1672 Op->StartLoc = S;
1673 Op->EndLoc = E;
1674 return Op;
1675 }
1676
Jim Grosbachd67641b2010-12-06 18:21:12 +00001677 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001678 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001679 Op->Reg.RegNum = RegNum;
1680 Op->StartLoc = S;
1681 Op->EndLoc = S;
1682 return Op;
1683 }
1684
Chris Lattner3a697562010-10-28 17:20:03 +00001685 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001686 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001687 Op->Tok.Data = Str.data();
1688 Op->Tok.Length = Str.size();
1689 Op->StartLoc = S;
1690 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001691 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001692 }
1693
Bill Wendling50d0f582010-11-18 23:43:05 +00001694 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001695 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001696 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001699 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001700 }
1701
Jim Grosbache8606dc2011-07-13 17:50:29 +00001702 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1703 unsigned SrcReg,
1704 unsigned ShiftReg,
1705 unsigned ShiftImm,
1706 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001707 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001708 Op->RegShiftedReg.ShiftTy = ShTy;
1709 Op->RegShiftedReg.SrcReg = SrcReg;
1710 Op->RegShiftedReg.ShiftReg = ShiftReg;
1711 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001712 Op->StartLoc = S;
1713 Op->EndLoc = E;
1714 return Op;
1715 }
1716
Owen Anderson92a20222011-07-21 18:54:16 +00001717 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1718 unsigned SrcReg,
1719 unsigned ShiftImm,
1720 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001721 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001722 Op->RegShiftedImm.ShiftTy = ShTy;
1723 Op->RegShiftedImm.SrcReg = SrcReg;
1724 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001725 Op->StartLoc = S;
1726 Op->EndLoc = E;
1727 return Op;
1728 }
1729
Jim Grosbach580f4a92011-07-25 22:20:28 +00001730 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001731 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001732 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001733 Op->ShifterImm.isASR = isASR;
1734 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001735 Op->StartLoc = S;
1736 Op->EndLoc = E;
1737 return Op;
1738 }
1739
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001740 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001741 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001742 Op->RotImm.Imm = Imm;
1743 Op->StartLoc = S;
1744 Op->EndLoc = E;
1745 return Op;
1746 }
1747
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001748 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1749 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001750 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001751 Op->Bitfield.LSB = LSB;
1752 Op->Bitfield.Width = Width;
1753 Op->StartLoc = S;
1754 Op->EndLoc = E;
1755 return Op;
1756 }
1757
Bill Wendling7729e062010-11-09 22:44:22 +00001758 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001759 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001760 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001761 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001762
Jim Grosbachd300b942011-09-13 22:56:44 +00001763 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001765 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001766 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001767 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001768
1769 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001770 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001771 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001772 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001773 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001774 Op->StartLoc = StartLoc;
1775 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001776 return Op;
1777 }
1778
Jim Grosbach862019c2011-10-18 23:02:30 +00001779 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1780 SMLoc S, SMLoc E) {
1781 ARMOperand *Op = new ARMOperand(k_VectorList);
1782 Op->VectorList.RegNum = RegNum;
1783 Op->VectorList.Count = Count;
1784 Op->StartLoc = S;
1785 Op->EndLoc = E;
1786 return Op;
1787 }
1788
Jim Grosbach460a9052011-10-07 23:56:00 +00001789 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1790 MCContext &Ctx) {
1791 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1792 Op->VectorIndex.Val = Idx;
1793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Chris Lattner3a697562010-10-28 17:20:03 +00001798 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001799 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001800 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001801 Op->StartLoc = S;
1802 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001803 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001804 }
1805
Jim Grosbach9d390362011-10-03 23:38:36 +00001806 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001807 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001808 Op->FPImm.Val = Val;
1809 Op->StartLoc = S;
1810 Op->EndLoc = S;
1811 return Op;
1812 }
1813
Jim Grosbach7ce05792011-08-03 23:50:40 +00001814 static ARMOperand *CreateMem(unsigned BaseRegNum,
1815 const MCConstantExpr *OffsetImm,
1816 unsigned OffsetRegNum,
1817 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001818 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001819 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001820 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001821 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001823 Op->Memory.BaseRegNum = BaseRegNum;
1824 Op->Memory.OffsetImm = OffsetImm;
1825 Op->Memory.OffsetRegNum = OffsetRegNum;
1826 Op->Memory.ShiftType = ShiftType;
1827 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001828 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001829 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001830 Op->StartLoc = S;
1831 Op->EndLoc = E;
1832 return Op;
1833 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001834
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001835 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1836 ARM_AM::ShiftOpc ShiftTy,
1837 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001839 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001840 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001841 Op->PostIdxReg.isAdd = isAdd;
1842 Op->PostIdxReg.ShiftTy = ShiftTy;
1843 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001846 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001847 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001848
1849 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001850 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001851 Op->MBOpt.Val = Opt;
1852 Op->StartLoc = S;
1853 Op->EndLoc = S;
1854 return Op;
1855 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001856
1857 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001858 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001859 Op->IFlags.Val = IFlags;
1860 Op->StartLoc = S;
1861 Op->EndLoc = S;
1862 return Op;
1863 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001864
1865 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001866 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001867 Op->MMask.Val = MMask;
1868 Op->StartLoc = S;
1869 Op->EndLoc = S;
1870 return Op;
1871 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001872};
1873
1874} // end anonymous namespace.
1875
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001876void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001877 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001878 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001879 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1880 << ") >";
1881 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001882 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001883 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001884 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001885 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001886 OS << "<ccout " << getReg() << ">";
1887 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001889 static const char *MaskStr[] = {
1890 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1891 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1892 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001893 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1894 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1895 break;
1896 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001898 OS << "<coprocessor number: " << getCoproc() << ">";
1899 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001900 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001901 OS << "<coprocessor register: " << getCoproc() << ">";
1902 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001903 case k_CoprocOption:
1904 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1905 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001906 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001907 OS << "<mask: " << getMSRMask() << ">";
1908 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001909 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001910 getImm()->print(OS);
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001913 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001916 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001917 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001918 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001919 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001920 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001921 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1922 << PostIdxReg.RegNum;
1923 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1924 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1925 << PostIdxReg.ShiftImm;
1926 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001927 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001928 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001929 OS << "<ARM_PROC::";
1930 unsigned IFlags = getProcIFlags();
1931 for (int i=2; i >= 0; --i)
1932 if (IFlags & (1 << i))
1933 OS << ARM_PROC::IFlagsToString(1 << i);
1934 OS << ">";
1935 break;
1936 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001937 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001938 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001939 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001941 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1942 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001943 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001945 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001946 << RegShiftedReg.SrcReg
1947 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1948 << ", " << RegShiftedReg.ShiftReg << ", "
1949 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001950 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001951 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001952 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001953 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001954 << RegShiftedImm.SrcReg
1955 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1956 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001957 << ">";
1958 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001960 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1961 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001963 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1964 << ", width: " << Bitfield.Width << ">";
1965 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 case k_RegisterList:
1967 case k_DPRRegisterList:
1968 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001969 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001970
Bill Wendling5fa22a12010-11-09 23:28:44 +00001971 const SmallVectorImpl<unsigned> &RegList = getRegList();
1972 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001973 I = RegList.begin(), E = RegList.end(); I != E; ) {
1974 OS << *I;
1975 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001976 }
1977
1978 OS << ">";
1979 break;
1980 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001981 case k_VectorList:
1982 OS << "<vector_list " << VectorList.Count << " * "
1983 << VectorList.RegNum << ">";
1984 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001986 OS << "'" << getToken() << "'";
1987 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001988 case k_VectorIndex:
1989 OS << "<vectorindex " << getVectorIndex() << ">";
1990 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001991 }
1992}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001993
1994/// @name Auto-generated Match Functions
1995/// {
1996
1997static unsigned MatchRegisterName(StringRef Name);
1998
1999/// }
2000
Bob Wilson69df7232011-02-03 21:46:10 +00002001bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2002 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002003 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002004
2005 return (RegNo == (unsigned)-1);
2006}
2007
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002008/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002009/// and if it is a register name the token is eaten and the register number is
2010/// returned. Otherwise return -1.
2011///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002012int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002013 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002014 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002015
Chris Lattnere5658fa2010-10-30 04:09:10 +00002016 // FIXME: Validate register for the current architecture; we have to do
2017 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002018 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002019 unsigned RegNum = MatchRegisterName(lowerCase);
2020 if (!RegNum) {
2021 RegNum = StringSwitch<unsigned>(lowerCase)
2022 .Case("r13", ARM::SP)
2023 .Case("r14", ARM::LR)
2024 .Case("r15", ARM::PC)
2025 .Case("ip", ARM::R12)
2026 .Default(0);
2027 }
2028 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002029
Chris Lattnere5658fa2010-10-30 04:09:10 +00002030 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002031
Chris Lattnere5658fa2010-10-30 04:09:10 +00002032 return RegNum;
2033}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002034
Jim Grosbach19906722011-07-13 18:49:30 +00002035// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2036// If a recoverable error occurs, return 1. If an irrecoverable error
2037// occurs, return -1. An irrecoverable error is one where tokens have been
2038// consumed in the process of trying to parse the shifter (i.e., when it is
2039// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002040int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002041 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2042 SMLoc S = Parser.getTok().getLoc();
2043 const AsmToken &Tok = Parser.getTok();
2044 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2045
Benjamin Kramer59085362011-11-06 20:37:06 +00002046 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002047 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2048 .Case("lsl", ARM_AM::lsl)
2049 .Case("lsr", ARM_AM::lsr)
2050 .Case("asr", ARM_AM::asr)
2051 .Case("ror", ARM_AM::ror)
2052 .Case("rrx", ARM_AM::rrx)
2053 .Default(ARM_AM::no_shift);
2054
2055 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002056 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002057
Jim Grosbache8606dc2011-07-13 17:50:29 +00002058 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002059
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 // The source register for the shift has already been added to the
2061 // operand list, so we need to pop it off and combine it into the shifted
2062 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002063 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002064 if (!PrevOp->isReg())
2065 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2066 int SrcReg = PrevOp->getReg();
2067 int64_t Imm = 0;
2068 int ShiftReg = 0;
2069 if (ShiftTy == ARM_AM::rrx) {
2070 // RRX Doesn't have an explicit shift amount. The encoder expects
2071 // the shift register to be the same as the source register. Seems odd,
2072 // but OK.
2073 ShiftReg = SrcReg;
2074 } else {
2075 // Figure out if this is shifted by a constant or a register (for non-RRX).
2076 if (Parser.getTok().is(AsmToken::Hash)) {
2077 Parser.Lex(); // Eat hash.
2078 SMLoc ImmLoc = Parser.getTok().getLoc();
2079 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002080 if (getParser().ParseExpression(ShiftExpr)) {
2081 Error(ImmLoc, "invalid immediate shift value");
2082 return -1;
2083 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002084 // The expression must be evaluatable as an immediate.
2085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002086 if (!CE) {
2087 Error(ImmLoc, "invalid immediate shift value");
2088 return -1;
2089 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002090 // Range check the immediate.
2091 // lsl, ror: 0 <= imm <= 31
2092 // lsr, asr: 0 <= imm <= 32
2093 Imm = CE->getValue();
2094 if (Imm < 0 ||
2095 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2096 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002097 Error(ImmLoc, "immediate shift value out of range");
2098 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002099 }
2100 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002101 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002103 if (ShiftReg == -1) {
2104 Error (L, "expected immediate or register in shift operand");
2105 return -1;
2106 }
2107 } else {
2108 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002109 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002110 return -1;
2111 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 }
2113
Owen Anderson92a20222011-07-21 18:54:16 +00002114 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2115 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002116 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002117 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002118 else
2119 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2120 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002121
Jim Grosbach19906722011-07-13 18:49:30 +00002122 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002123}
2124
2125
Bill Wendling50d0f582010-11-18 23:43:05 +00002126/// Try to parse a register name. The token must be an Identifier when called.
2127/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2128/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002129///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002130/// TODO this is likely to change to allow different register types and or to
2131/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002132bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002133tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002134 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002135 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002136 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002137 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002138
Bill Wendling50d0f582010-11-18 23:43:05 +00002139 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002140
Chris Lattnere5658fa2010-10-30 04:09:10 +00002141 const AsmToken &ExclaimTok = Parser.getTok();
2142 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002143 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2144 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002145 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002146 return false;
2147 }
2148
2149 // Also check for an index operand. This is only legal for vector registers,
2150 // but that'll get caught OK in operand matching, so we don't need to
2151 // explicitly filter everything else out here.
2152 if (Parser.getTok().is(AsmToken::LBrac)) {
2153 SMLoc SIdx = Parser.getTok().getLoc();
2154 Parser.Lex(); // Eat left bracket token.
2155
2156 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002157 if (getParser().ParseExpression(ImmVal))
2158 return MatchOperand_ParseFail;
2159 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2160 if (!MCE) {
2161 TokError("immediate value expected for vector index");
2162 return MatchOperand_ParseFail;
2163 }
2164
2165 SMLoc E = Parser.getTok().getLoc();
2166 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2167 Error(E, "']' expected");
2168 return MatchOperand_ParseFail;
2169 }
2170
2171 Parser.Lex(); // Eat right bracket token.
2172
2173 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2174 SIdx, E,
2175 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002176 }
2177
Bill Wendling50d0f582010-11-18 23:43:05 +00002178 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002179}
2180
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002181/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2182/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2183/// "c5", ...
2184static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002185 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2186 // but efficient.
2187 switch (Name.size()) {
2188 default: break;
2189 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002190 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002191 return -1;
2192 switch (Name[1]) {
2193 default: return -1;
2194 case '0': return 0;
2195 case '1': return 1;
2196 case '2': return 2;
2197 case '3': return 3;
2198 case '4': return 4;
2199 case '5': return 5;
2200 case '6': return 6;
2201 case '7': return 7;
2202 case '8': return 8;
2203 case '9': return 9;
2204 }
2205 break;
2206 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002207 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002208 return -1;
2209 switch (Name[2]) {
2210 default: return -1;
2211 case '0': return 10;
2212 case '1': return 11;
2213 case '2': return 12;
2214 case '3': return 13;
2215 case '4': return 14;
2216 case '5': return 15;
2217 }
2218 break;
2219 }
2220
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002221 return -1;
2222}
2223
Jim Grosbach89df9962011-08-26 21:43:41 +00002224/// parseITCondCode - Try to parse a condition code for an IT instruction.
2225ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2226parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2227 SMLoc S = Parser.getTok().getLoc();
2228 const AsmToken &Tok = Parser.getTok();
2229 if (!Tok.is(AsmToken::Identifier))
2230 return MatchOperand_NoMatch;
2231 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2232 .Case("eq", ARMCC::EQ)
2233 .Case("ne", ARMCC::NE)
2234 .Case("hs", ARMCC::HS)
2235 .Case("cs", ARMCC::HS)
2236 .Case("lo", ARMCC::LO)
2237 .Case("cc", ARMCC::LO)
2238 .Case("mi", ARMCC::MI)
2239 .Case("pl", ARMCC::PL)
2240 .Case("vs", ARMCC::VS)
2241 .Case("vc", ARMCC::VC)
2242 .Case("hi", ARMCC::HI)
2243 .Case("ls", ARMCC::LS)
2244 .Case("ge", ARMCC::GE)
2245 .Case("lt", ARMCC::LT)
2246 .Case("gt", ARMCC::GT)
2247 .Case("le", ARMCC::LE)
2248 .Case("al", ARMCC::AL)
2249 .Default(~0U);
2250 if (CC == ~0U)
2251 return MatchOperand_NoMatch;
2252 Parser.Lex(); // Eat the token.
2253
2254 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2255
2256 return MatchOperand_Success;
2257}
2258
Jim Grosbach43904292011-07-25 20:14:50 +00002259/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002260/// token must be an Identifier when called, and if it is a coprocessor
2261/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002263parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002264 SMLoc S = Parser.getTok().getLoc();
2265 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002266 if (Tok.isNot(AsmToken::Identifier))
2267 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002269 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002270 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002271 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002272
2273 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002274 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002275 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002276}
2277
Jim Grosbach43904292011-07-25 20:14:50 +00002278/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002279/// token must be an Identifier when called, and if it is a coprocessor
2280/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002281ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002282parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002283 SMLoc S = Parser.getTok().getLoc();
2284 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002285 if (Tok.isNot(AsmToken::Identifier))
2286 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002287
2288 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2289 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002290 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002291
2292 Parser.Lex(); // Eat identifier token.
2293 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002294 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002295}
2296
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002297/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2298/// coproc_option : '{' imm0_255 '}'
2299ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2300parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2301 SMLoc S = Parser.getTok().getLoc();
2302
2303 // If this isn't a '{', this isn't a coprocessor immediate operand.
2304 if (Parser.getTok().isNot(AsmToken::LCurly))
2305 return MatchOperand_NoMatch;
2306 Parser.Lex(); // Eat the '{'
2307
2308 const MCExpr *Expr;
2309 SMLoc Loc = Parser.getTok().getLoc();
2310 if (getParser().ParseExpression(Expr)) {
2311 Error(Loc, "illegal expression");
2312 return MatchOperand_ParseFail;
2313 }
2314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2315 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2316 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2317 return MatchOperand_ParseFail;
2318 }
2319 int Val = CE->getValue();
2320
2321 // Check for and consume the closing '}'
2322 if (Parser.getTok().isNot(AsmToken::RCurly))
2323 return MatchOperand_ParseFail;
2324 SMLoc E = Parser.getTok().getLoc();
2325 Parser.Lex(); // Eat the '}'
2326
2327 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2328 return MatchOperand_Success;
2329}
2330
Jim Grosbachd0588e22011-09-14 18:08:35 +00002331// For register list parsing, we need to map from raw GPR register numbering
2332// to the enumeration values. The enumeration values aren't sorted by
2333// register number due to our using "sp", "lr" and "pc" as canonical names.
2334static unsigned getNextRegister(unsigned Reg) {
2335 // If this is a GPR, we need to do it manually, otherwise we can rely
2336 // on the sort ordering of the enumeration since the other reg-classes
2337 // are sane.
2338 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2339 return Reg + 1;
2340 switch(Reg) {
2341 default: assert(0 && "Invalid GPR number!");
2342 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2343 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2344 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2345 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2346 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2347 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2348 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2349 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2350 }
2351}
2352
Jim Grosbachce485e72011-11-11 21:27:40 +00002353// Return the low-subreg of a given Q register.
2354static unsigned getDRegFromQReg(unsigned QReg) {
2355 switch (QReg) {
2356 default: llvm_unreachable("expected a Q register!");
2357 case ARM::Q0: return ARM::D0;
2358 case ARM::Q1: return ARM::D2;
2359 case ARM::Q2: return ARM::D4;
2360 case ARM::Q3: return ARM::D6;
2361 case ARM::Q4: return ARM::D8;
2362 case ARM::Q5: return ARM::D10;
2363 case ARM::Q6: return ARM::D12;
2364 case ARM::Q7: return ARM::D14;
2365 case ARM::Q8: return ARM::D16;
2366 case ARM::Q9: return ARM::D19;
2367 case ARM::Q10: return ARM::D20;
2368 case ARM::Q11: return ARM::D22;
2369 case ARM::Q12: return ARM::D24;
2370 case ARM::Q13: return ARM::D26;
2371 case ARM::Q14: return ARM::D28;
2372 case ARM::Q15: return ARM::D30;
2373 }
2374}
2375
Jim Grosbachd0588e22011-09-14 18:08:35 +00002376/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002377bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002378parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002379 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002380 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002381 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002382 Parser.Lex(); // Eat '{' token.
2383 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002384
Jim Grosbachd0588e22011-09-14 18:08:35 +00002385 // Check the first register in the list to see what register class
2386 // this is a list of.
2387 int Reg = tryParseRegister();
2388 if (Reg == -1)
2389 return Error(RegLoc, "register expected");
2390
Jim Grosbachce485e72011-11-11 21:27:40 +00002391 // The reglist instructions have at most 16 registers, so reserve
2392 // space for that many.
2393 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2394
2395 // Allow Q regs and just interpret them as the two D sub-registers.
2396 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2397 Reg = getDRegFromQReg(Reg);
2398 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2399 ++Reg;
2400 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002401 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002402 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2403 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2404 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2405 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2406 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2407 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2408 else
2409 return Error(RegLoc, "invalid register in register list");
2410
Jim Grosbachce485e72011-11-11 21:27:40 +00002411 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002412 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002413
Jim Grosbachd0588e22011-09-14 18:08:35 +00002414 // This starts immediately after the first register token in the list,
2415 // so we can see either a comma or a minus (range separator) as a legal
2416 // next token.
2417 while (Parser.getTok().is(AsmToken::Comma) ||
2418 Parser.getTok().is(AsmToken::Minus)) {
2419 if (Parser.getTok().is(AsmToken::Minus)) {
2420 Parser.Lex(); // Eat the comma.
2421 SMLoc EndLoc = Parser.getTok().getLoc();
2422 int EndReg = tryParseRegister();
2423 if (EndReg == -1)
2424 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002425 // Allow Q regs and just interpret them as the two D sub-registers.
2426 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2427 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002428 // If the register is the same as the start reg, there's nothing
2429 // more to do.
2430 if (Reg == EndReg)
2431 continue;
2432 // The register must be in the same register class as the first.
2433 if (!RC->contains(EndReg))
2434 return Error(EndLoc, "invalid register in register list");
2435 // Ranges must go from low to high.
2436 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2437 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002438
Jim Grosbachd0588e22011-09-14 18:08:35 +00002439 // Add all the registers in the range to the register list.
2440 while (Reg != EndReg) {
2441 Reg = getNextRegister(Reg);
2442 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2443 }
2444 continue;
2445 }
2446 Parser.Lex(); // Eat the comma.
2447 RegLoc = Parser.getTok().getLoc();
2448 int OldReg = Reg;
2449 Reg = tryParseRegister();
2450 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002451 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002452 // Allow Q regs and just interpret them as the two D sub-registers.
2453 bool isQReg = false;
2454 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2455 Reg = getDRegFromQReg(Reg);
2456 isQReg = true;
2457 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002458 // The register must be in the same register class as the first.
2459 if (!RC->contains(Reg))
2460 return Error(RegLoc, "invalid register in register list");
2461 // List must be monotonically increasing.
2462 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2463 return Error(RegLoc, "register list not in ascending order");
2464 // VFP register lists must also be contiguous.
2465 // It's OK to use the enumeration values directly here rather, as the
2466 // VFP register classes have the enum sorted properly.
2467 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2468 Reg != OldReg + 1)
2469 return Error(RegLoc, "non-contiguous register range");
2470 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002471 if (isQReg)
2472 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002473 }
2474
Jim Grosbachd0588e22011-09-14 18:08:35 +00002475 SMLoc E = Parser.getTok().getLoc();
2476 if (Parser.getTok().isNot(AsmToken::RCurly))
2477 return Error(E, "'}' expected");
2478 Parser.Lex(); // Eat '}' token.
2479
Bill Wendling50d0f582010-11-18 23:43:05 +00002480 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2481 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002482}
2483
Jim Grosbach862019c2011-10-18 23:02:30 +00002484// parse a vector register list
2485ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2486parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2487 if(Parser.getTok().isNot(AsmToken::LCurly))
2488 return MatchOperand_NoMatch;
2489
2490 SMLoc S = Parser.getTok().getLoc();
2491 Parser.Lex(); // Eat '{' token.
2492 SMLoc RegLoc = Parser.getTok().getLoc();
2493
2494 int Reg = tryParseRegister();
2495 if (Reg == -1) {
2496 Error(RegLoc, "register expected");
2497 return MatchOperand_ParseFail;
2498 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002499 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002500 unsigned FirstReg = Reg;
2501 // The list is of D registers, but we also allow Q regs and just interpret
2502 // them as the two D sub-registers.
2503 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2504 FirstReg = Reg = getDRegFromQReg(Reg);
2505 ++Reg;
2506 ++Count;
2507 }
2508
Jim Grosbach862019c2011-10-18 23:02:30 +00002509 while (Parser.getTok().is(AsmToken::Comma)) {
2510 Parser.Lex(); // Eat the comma.
2511 RegLoc = Parser.getTok().getLoc();
2512 int OldReg = Reg;
2513 Reg = tryParseRegister();
2514 if (Reg == -1) {
2515 Error(RegLoc, "register expected");
2516 return MatchOperand_ParseFail;
2517 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002518 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002519 // It's OK to use the enumeration values directly here rather, as the
2520 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002521 //
2522 // The list is of D registers, but we also allow Q regs and just interpret
2523 // them as the two D sub-registers.
2524 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2525 Reg = getDRegFromQReg(Reg);
2526 if (Reg != OldReg + 1) {
2527 Error(RegLoc, "non-contiguous register range");
2528 return MatchOperand_ParseFail;
2529 }
2530 ++Reg;
2531 Count += 2;
2532 continue;
2533 }
2534 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002535 if (Reg != OldReg + 1) {
2536 Error(RegLoc, "non-contiguous register range");
2537 return MatchOperand_ParseFail;
2538 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002539 ++Count;
2540 }
2541
2542 SMLoc E = Parser.getTok().getLoc();
2543 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2544 Error(E, "'}' expected");
2545 return MatchOperand_ParseFail;
2546 }
2547 Parser.Lex(); // Eat '}' token.
2548
2549 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2550 return MatchOperand_Success;
2551}
2552
Jim Grosbach43904292011-07-25 20:14:50 +00002553/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002554ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002555parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002556 SMLoc S = Parser.getTok().getLoc();
2557 const AsmToken &Tok = Parser.getTok();
2558 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2559 StringRef OptStr = Tok.getString();
2560
2561 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2562 .Case("sy", ARM_MB::SY)
2563 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002564 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002565 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002566 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002567 .Case("ishst", ARM_MB::ISHST)
2568 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002569 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002570 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002571 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002572 .Case("osh", ARM_MB::OSH)
2573 .Case("oshst", ARM_MB::OSHST)
2574 .Default(~0U);
2575
2576 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002577 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002578
2579 Parser.Lex(); // Eat identifier token.
2580 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002581 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002582}
2583
Jim Grosbach43904292011-07-25 20:14:50 +00002584/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002585ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002586parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002587 SMLoc S = Parser.getTok().getLoc();
2588 const AsmToken &Tok = Parser.getTok();
2589 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2590 StringRef IFlagsStr = Tok.getString();
2591
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002592 // An iflags string of "none" is interpreted to mean that none of the AIF
2593 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002594 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002595 if (IFlagsStr != "none") {
2596 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2597 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2598 .Case("a", ARM_PROC::A)
2599 .Case("i", ARM_PROC::I)
2600 .Case("f", ARM_PROC::F)
2601 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002602
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002603 // If some specific iflag is already set, it means that some letter is
2604 // present more than once, this is not acceptable.
2605 if (Flag == ~0U || (IFlags & Flag))
2606 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002607
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002608 IFlags |= Flag;
2609 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002610 }
2611
2612 Parser.Lex(); // Eat identifier token.
2613 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2614 return MatchOperand_Success;
2615}
2616
Jim Grosbach43904292011-07-25 20:14:50 +00002617/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002618ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002619parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002620 SMLoc S = Parser.getTok().getLoc();
2621 const AsmToken &Tok = Parser.getTok();
2622 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2623 StringRef Mask = Tok.getString();
2624
James Molloyacad68d2011-09-28 14:21:38 +00002625 if (isMClass()) {
2626 // See ARMv6-M 10.1.1
2627 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2628 .Case("apsr", 0)
2629 .Case("iapsr", 1)
2630 .Case("eapsr", 2)
2631 .Case("xpsr", 3)
2632 .Case("ipsr", 5)
2633 .Case("epsr", 6)
2634 .Case("iepsr", 7)
2635 .Case("msp", 8)
2636 .Case("psp", 9)
2637 .Case("primask", 16)
2638 .Case("basepri", 17)
2639 .Case("basepri_max", 18)
2640 .Case("faultmask", 19)
2641 .Case("control", 20)
2642 .Default(~0U);
2643
2644 if (FlagsVal == ~0U)
2645 return MatchOperand_NoMatch;
2646
2647 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2648 // basepri, basepri_max and faultmask only valid for V7m.
2649 return MatchOperand_NoMatch;
2650
2651 Parser.Lex(); // Eat identifier token.
2652 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2653 return MatchOperand_Success;
2654 }
2655
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002656 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2657 size_t Start = 0, Next = Mask.find('_');
2658 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002659 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002660 if (Next != StringRef::npos)
2661 Flags = Mask.slice(Next+1, Mask.size());
2662
2663 // FlagsVal contains the complete mask:
2664 // 3-0: Mask
2665 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2666 unsigned FlagsVal = 0;
2667
2668 if (SpecReg == "apsr") {
2669 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002670 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002671 .Case("g", 0x4) // same as CPSR_s
2672 .Case("nzcvqg", 0xc) // same as CPSR_fs
2673 .Default(~0U);
2674
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002675 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002676 if (!Flags.empty())
2677 return MatchOperand_NoMatch;
2678 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002679 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002680 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002681 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002682 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2683 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002684 for (int i = 0, e = Flags.size(); i != e; ++i) {
2685 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2686 .Case("c", 1)
2687 .Case("x", 2)
2688 .Case("s", 4)
2689 .Case("f", 8)
2690 .Default(~0U);
2691
2692 // If some specific flag is already set, it means that some letter is
2693 // present more than once, this is not acceptable.
2694 if (FlagsVal == ~0U || (FlagsVal & Flag))
2695 return MatchOperand_NoMatch;
2696 FlagsVal |= Flag;
2697 }
2698 } else // No match for special register.
2699 return MatchOperand_NoMatch;
2700
Owen Anderson7784f1d2011-10-21 18:43:28 +00002701 // Special register without flags is NOT equivalent to "fc" flags.
2702 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2703 // two lines would enable gas compatibility at the expense of breaking
2704 // round-tripping.
2705 //
2706 // if (!FlagsVal)
2707 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002708
2709 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2710 if (SpecReg == "spsr")
2711 FlagsVal |= 16;
2712
2713 Parser.Lex(); // Eat identifier token.
2714 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2715 return MatchOperand_Success;
2716}
2717
Jim Grosbachf6c05252011-07-21 17:23:04 +00002718ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2719parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2720 int Low, int High) {
2721 const AsmToken &Tok = Parser.getTok();
2722 if (Tok.isNot(AsmToken::Identifier)) {
2723 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2724 return MatchOperand_ParseFail;
2725 }
2726 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002727 std::string LowerOp = Op.lower();
2728 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002729 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2730 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2731 return MatchOperand_ParseFail;
2732 }
2733 Parser.Lex(); // Eat shift type token.
2734
2735 // There must be a '#' and a shift amount.
2736 if (Parser.getTok().isNot(AsmToken::Hash)) {
2737 Error(Parser.getTok().getLoc(), "'#' expected");
2738 return MatchOperand_ParseFail;
2739 }
2740 Parser.Lex(); // Eat hash token.
2741
2742 const MCExpr *ShiftAmount;
2743 SMLoc Loc = Parser.getTok().getLoc();
2744 if (getParser().ParseExpression(ShiftAmount)) {
2745 Error(Loc, "illegal expression");
2746 return MatchOperand_ParseFail;
2747 }
2748 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2749 if (!CE) {
2750 Error(Loc, "constant expression expected");
2751 return MatchOperand_ParseFail;
2752 }
2753 int Val = CE->getValue();
2754 if (Val < Low || Val > High) {
2755 Error(Loc, "immediate value out of range");
2756 return MatchOperand_ParseFail;
2757 }
2758
2759 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2760
2761 return MatchOperand_Success;
2762}
2763
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002764ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2765parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2766 const AsmToken &Tok = Parser.getTok();
2767 SMLoc S = Tok.getLoc();
2768 if (Tok.isNot(AsmToken::Identifier)) {
2769 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2770 return MatchOperand_ParseFail;
2771 }
2772 int Val = StringSwitch<int>(Tok.getString())
2773 .Case("be", 1)
2774 .Case("le", 0)
2775 .Default(-1);
2776 Parser.Lex(); // Eat the token.
2777
2778 if (Val == -1) {
2779 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2780 return MatchOperand_ParseFail;
2781 }
2782 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2783 getContext()),
2784 S, Parser.getTok().getLoc()));
2785 return MatchOperand_Success;
2786}
2787
Jim Grosbach580f4a92011-07-25 22:20:28 +00002788/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2789/// instructions. Legal values are:
2790/// lsl #n 'n' in [0,31]
2791/// asr #n 'n' in [1,32]
2792/// n == 32 encoded as n == 0.
2793ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2794parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2795 const AsmToken &Tok = Parser.getTok();
2796 SMLoc S = Tok.getLoc();
2797 if (Tok.isNot(AsmToken::Identifier)) {
2798 Error(S, "shift operator 'asr' or 'lsl' expected");
2799 return MatchOperand_ParseFail;
2800 }
2801 StringRef ShiftName = Tok.getString();
2802 bool isASR;
2803 if (ShiftName == "lsl" || ShiftName == "LSL")
2804 isASR = false;
2805 else if (ShiftName == "asr" || ShiftName == "ASR")
2806 isASR = true;
2807 else {
2808 Error(S, "shift operator 'asr' or 'lsl' expected");
2809 return MatchOperand_ParseFail;
2810 }
2811 Parser.Lex(); // Eat the operator.
2812
2813 // A '#' and a shift amount.
2814 if (Parser.getTok().isNot(AsmToken::Hash)) {
2815 Error(Parser.getTok().getLoc(), "'#' expected");
2816 return MatchOperand_ParseFail;
2817 }
2818 Parser.Lex(); // Eat hash token.
2819
2820 const MCExpr *ShiftAmount;
2821 SMLoc E = Parser.getTok().getLoc();
2822 if (getParser().ParseExpression(ShiftAmount)) {
2823 Error(E, "malformed shift expression");
2824 return MatchOperand_ParseFail;
2825 }
2826 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2827 if (!CE) {
2828 Error(E, "shift amount must be an immediate");
2829 return MatchOperand_ParseFail;
2830 }
2831
2832 int64_t Val = CE->getValue();
2833 if (isASR) {
2834 // Shift amount must be in [1,32]
2835 if (Val < 1 || Val > 32) {
2836 Error(E, "'asr' shift amount must be in range [1,32]");
2837 return MatchOperand_ParseFail;
2838 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002839 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2840 if (isThumb() && Val == 32) {
2841 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2842 return MatchOperand_ParseFail;
2843 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002844 if (Val == 32) Val = 0;
2845 } else {
2846 // Shift amount must be in [1,32]
2847 if (Val < 0 || Val > 31) {
2848 Error(E, "'lsr' shift amount must be in range [0,31]");
2849 return MatchOperand_ParseFail;
2850 }
2851 }
2852
2853 E = Parser.getTok().getLoc();
2854 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2855
2856 return MatchOperand_Success;
2857}
2858
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002859/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2860/// of instructions. Legal values are:
2861/// ror #n 'n' in {0, 8, 16, 24}
2862ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2863parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2864 const AsmToken &Tok = Parser.getTok();
2865 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002866 if (Tok.isNot(AsmToken::Identifier))
2867 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002868 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002869 if (ShiftName != "ror" && ShiftName != "ROR")
2870 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002871 Parser.Lex(); // Eat the operator.
2872
2873 // A '#' and a rotate amount.
2874 if (Parser.getTok().isNot(AsmToken::Hash)) {
2875 Error(Parser.getTok().getLoc(), "'#' expected");
2876 return MatchOperand_ParseFail;
2877 }
2878 Parser.Lex(); // Eat hash token.
2879
2880 const MCExpr *ShiftAmount;
2881 SMLoc E = Parser.getTok().getLoc();
2882 if (getParser().ParseExpression(ShiftAmount)) {
2883 Error(E, "malformed rotate expression");
2884 return MatchOperand_ParseFail;
2885 }
2886 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2887 if (!CE) {
2888 Error(E, "rotate amount must be an immediate");
2889 return MatchOperand_ParseFail;
2890 }
2891
2892 int64_t Val = CE->getValue();
2893 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2894 // normally, zero is represented in asm by omitting the rotate operand
2895 // entirely.
2896 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2897 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2898 return MatchOperand_ParseFail;
2899 }
2900
2901 E = Parser.getTok().getLoc();
2902 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2903
2904 return MatchOperand_Success;
2905}
2906
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002907ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2908parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2909 SMLoc S = Parser.getTok().getLoc();
2910 // The bitfield descriptor is really two operands, the LSB and the width.
2911 if (Parser.getTok().isNot(AsmToken::Hash)) {
2912 Error(Parser.getTok().getLoc(), "'#' expected");
2913 return MatchOperand_ParseFail;
2914 }
2915 Parser.Lex(); // Eat hash token.
2916
2917 const MCExpr *LSBExpr;
2918 SMLoc E = Parser.getTok().getLoc();
2919 if (getParser().ParseExpression(LSBExpr)) {
2920 Error(E, "malformed immediate expression");
2921 return MatchOperand_ParseFail;
2922 }
2923 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2924 if (!CE) {
2925 Error(E, "'lsb' operand must be an immediate");
2926 return MatchOperand_ParseFail;
2927 }
2928
2929 int64_t LSB = CE->getValue();
2930 // The LSB must be in the range [0,31]
2931 if (LSB < 0 || LSB > 31) {
2932 Error(E, "'lsb' operand must be in the range [0,31]");
2933 return MatchOperand_ParseFail;
2934 }
2935 E = Parser.getTok().getLoc();
2936
2937 // Expect another immediate operand.
2938 if (Parser.getTok().isNot(AsmToken::Comma)) {
2939 Error(Parser.getTok().getLoc(), "too few operands");
2940 return MatchOperand_ParseFail;
2941 }
2942 Parser.Lex(); // Eat hash token.
2943 if (Parser.getTok().isNot(AsmToken::Hash)) {
2944 Error(Parser.getTok().getLoc(), "'#' expected");
2945 return MatchOperand_ParseFail;
2946 }
2947 Parser.Lex(); // Eat hash token.
2948
2949 const MCExpr *WidthExpr;
2950 if (getParser().ParseExpression(WidthExpr)) {
2951 Error(E, "malformed immediate expression");
2952 return MatchOperand_ParseFail;
2953 }
2954 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2955 if (!CE) {
2956 Error(E, "'width' operand must be an immediate");
2957 return MatchOperand_ParseFail;
2958 }
2959
2960 int64_t Width = CE->getValue();
2961 // The LSB must be in the range [1,32-lsb]
2962 if (Width < 1 || Width > 32 - LSB) {
2963 Error(E, "'width' operand must be in the range [1,32-lsb]");
2964 return MatchOperand_ParseFail;
2965 }
2966 E = Parser.getTok().getLoc();
2967
2968 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2969
2970 return MatchOperand_Success;
2971}
2972
Jim Grosbach7ce05792011-08-03 23:50:40 +00002973ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2974parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2975 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002976 // postidx_reg := '+' register {, shift}
2977 // | '-' register {, shift}
2978 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002979
2980 // This method must return MatchOperand_NoMatch without consuming any tokens
2981 // in the case where there is no match, as other alternatives take other
2982 // parse methods.
2983 AsmToken Tok = Parser.getTok();
2984 SMLoc S = Tok.getLoc();
2985 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002986 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002987 int Reg = -1;
2988 if (Tok.is(AsmToken::Plus)) {
2989 Parser.Lex(); // Eat the '+' token.
2990 haveEaten = true;
2991 } else if (Tok.is(AsmToken::Minus)) {
2992 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002993 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002994 haveEaten = true;
2995 }
2996 if (Parser.getTok().is(AsmToken::Identifier))
2997 Reg = tryParseRegister();
2998 if (Reg == -1) {
2999 if (!haveEaten)
3000 return MatchOperand_NoMatch;
3001 Error(Parser.getTok().getLoc(), "register expected");
3002 return MatchOperand_ParseFail;
3003 }
3004 SMLoc E = Parser.getTok().getLoc();
3005
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003006 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3007 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003008 if (Parser.getTok().is(AsmToken::Comma)) {
3009 Parser.Lex(); // Eat the ','.
3010 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3011 return MatchOperand_ParseFail;
3012 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003013
3014 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3015 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003016
3017 return MatchOperand_Success;
3018}
3019
Jim Grosbach251bf252011-08-10 21:56:18 +00003020ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3021parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3022 // Check for a post-index addressing register operand. Specifically:
3023 // am3offset := '+' register
3024 // | '-' register
3025 // | register
3026 // | # imm
3027 // | # + imm
3028 // | # - imm
3029
3030 // This method must return MatchOperand_NoMatch without consuming any tokens
3031 // in the case where there is no match, as other alternatives take other
3032 // parse methods.
3033 AsmToken Tok = Parser.getTok();
3034 SMLoc S = Tok.getLoc();
3035
3036 // Do immediates first, as we always parse those if we have a '#'.
3037 if (Parser.getTok().is(AsmToken::Hash)) {
3038 Parser.Lex(); // Eat the '#'.
3039 // Explicitly look for a '-', as we need to encode negative zero
3040 // differently.
3041 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3042 const MCExpr *Offset;
3043 if (getParser().ParseExpression(Offset))
3044 return MatchOperand_ParseFail;
3045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3046 if (!CE) {
3047 Error(S, "constant expression expected");
3048 return MatchOperand_ParseFail;
3049 }
3050 SMLoc E = Tok.getLoc();
3051 // Negative zero is encoded as the flag value INT32_MIN.
3052 int32_t Val = CE->getValue();
3053 if (isNegative && Val == 0)
3054 Val = INT32_MIN;
3055
3056 Operands.push_back(
3057 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3058
3059 return MatchOperand_Success;
3060 }
3061
3062
3063 bool haveEaten = false;
3064 bool isAdd = true;
3065 int Reg = -1;
3066 if (Tok.is(AsmToken::Plus)) {
3067 Parser.Lex(); // Eat the '+' token.
3068 haveEaten = true;
3069 } else if (Tok.is(AsmToken::Minus)) {
3070 Parser.Lex(); // Eat the '-' token.
3071 isAdd = false;
3072 haveEaten = true;
3073 }
3074 if (Parser.getTok().is(AsmToken::Identifier))
3075 Reg = tryParseRegister();
3076 if (Reg == -1) {
3077 if (!haveEaten)
3078 return MatchOperand_NoMatch;
3079 Error(Parser.getTok().getLoc(), "register expected");
3080 return MatchOperand_ParseFail;
3081 }
3082 SMLoc E = Parser.getTok().getLoc();
3083
3084 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3085 0, S, E));
3086
3087 return MatchOperand_Success;
3088}
3089
Jim Grosbacha77295d2011-09-08 22:07:06 +00003090/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3091/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3092/// when they refer multiple MIOperands inside a single one.
3093bool ARMAsmParser::
3094cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3095 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3096 // Rt, Rt2
3097 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3098 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3099 // Create a writeback register dummy placeholder.
3100 Inst.addOperand(MCOperand::CreateReg(0));
3101 // addr
3102 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3103 // pred
3104 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3105 return true;
3106}
3107
3108/// cvtT2StrdPre - Convert parsed operands to MCInst.
3109/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3110/// when they refer multiple MIOperands inside a single one.
3111bool ARMAsmParser::
3112cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3113 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3114 // Create a writeback register dummy placeholder.
3115 Inst.addOperand(MCOperand::CreateReg(0));
3116 // Rt, Rt2
3117 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3118 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3119 // addr
3120 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3121 // pred
3122 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3123 return true;
3124}
3125
Jim Grosbacheeec0252011-09-08 00:39:19 +00003126/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3127/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3128/// when they refer multiple MIOperands inside a single one.
3129bool ARMAsmParser::
3130cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3131 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3132 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3133
3134 // Create a writeback register dummy placeholder.
3135 Inst.addOperand(MCOperand::CreateImm(0));
3136
3137 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3138 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3139 return true;
3140}
3141
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003142/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3143/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3144/// when they refer multiple MIOperands inside a single one.
3145bool ARMAsmParser::
3146cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3147 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3148 // Create a writeback register dummy placeholder.
3149 Inst.addOperand(MCOperand::CreateImm(0));
3150 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3151 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3153 return true;
3154}
3155
Jim Grosbach1355cf12011-07-26 17:10:22 +00003156/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003157/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3158/// when they refer multiple MIOperands inside a single one.
3159bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003160cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003161 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3162 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3163
3164 // Create a writeback register dummy placeholder.
3165 Inst.addOperand(MCOperand::CreateImm(0));
3166
Jim Grosbach7ce05792011-08-03 23:50:40 +00003167 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003168 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3169 return true;
3170}
3171
Owen Anderson9ab0f252011-08-26 20:43:14 +00003172/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3173/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3174/// when they refer multiple MIOperands inside a single one.
3175bool ARMAsmParser::
3176cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3177 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3178 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3179
3180 // Create a writeback register dummy placeholder.
3181 Inst.addOperand(MCOperand::CreateImm(0));
3182
3183 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3184 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3185 return true;
3186}
3187
3188
Jim Grosbach548340c2011-08-11 19:22:40 +00003189/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3190/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3191/// when they refer multiple MIOperands inside a single one.
3192bool ARMAsmParser::
3193cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3194 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3195 // Create a writeback register dummy placeholder.
3196 Inst.addOperand(MCOperand::CreateImm(0));
3197 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3198 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3199 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3200 return true;
3201}
3202
Jim Grosbach1355cf12011-07-26 17:10:22 +00003203/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003204/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3205/// when they refer multiple MIOperands inside a single one.
3206bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003207cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003208 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3209 // Create a writeback register dummy placeholder.
3210 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003211 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3212 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3213 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003214 return true;
3215}
3216
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003217/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3218/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3219/// when they refer multiple MIOperands inside a single one.
3220bool ARMAsmParser::
3221cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3222 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3223 // Create a writeback register dummy placeholder.
3224 Inst.addOperand(MCOperand::CreateImm(0));
3225 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3226 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3227 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3228 return true;
3229}
3230
Jim Grosbach7ce05792011-08-03 23:50:40 +00003231/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003238 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003239 // Create a writeback register dummy placeholder.
3240 Inst.addOperand(MCOperand::CreateImm(0));
3241 // addr
3242 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3243 // offset
3244 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3245 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003246 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3247 return true;
3248}
3249
Jim Grosbach7ce05792011-08-03 23:50:40 +00003250/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003251/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3252/// when they refer multiple MIOperands inside a single one.
3253bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003254cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3255 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3256 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003257 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003258 // Create a writeback register dummy placeholder.
3259 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003260 // addr
3261 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3262 // offset
3263 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3264 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003265 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3266 return true;
3267}
3268
Jim Grosbach7ce05792011-08-03 23:50:40 +00003269/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003270/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3271/// when they refer multiple MIOperands inside a single one.
3272bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003273cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3274 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003275 // Create a writeback register dummy placeholder.
3276 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003277 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003278 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003279 // addr
3280 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3281 // offset
3282 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3283 // pred
3284 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3285 return true;
3286}
3287
3288/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3289/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3290/// when they refer multiple MIOperands inside a single one.
3291bool ARMAsmParser::
3292cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3293 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3294 // Create a writeback register dummy placeholder.
3295 Inst.addOperand(MCOperand::CreateImm(0));
3296 // Rt
3297 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3298 // addr
3299 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3300 // offset
3301 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3302 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003303 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3304 return true;
3305}
3306
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003307/// cvtLdrdPre - 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::
3311cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3312 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3313 // Rt, Rt2
3314 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3315 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3316 // Create a writeback register dummy placeholder.
3317 Inst.addOperand(MCOperand::CreateImm(0));
3318 // addr
3319 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3320 // pred
3321 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3322 return true;
3323}
3324
Jim Grosbach14605d12011-08-11 20:28:23 +00003325/// cvtStrdPre - 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::
3329cvtStrdPre(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3331 // Create a writeback register dummy placeholder.
3332 Inst.addOperand(MCOperand::CreateImm(0));
3333 // Rt, Rt2
3334 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3335 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3336 // addr
3337 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3338 // pred
3339 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3340 return true;
3341}
3342
Jim Grosbach623a4542011-08-10 22:42:16 +00003343/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3344/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3345/// when they refer multiple MIOperands inside a single one.
3346bool ARMAsmParser::
3347cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3348 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3349 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3350 // Create a writeback register dummy placeholder.
3351 Inst.addOperand(MCOperand::CreateImm(0));
3352 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3353 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3354 return true;
3355}
3356
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003357/// cvtThumbMultiple- Convert parsed operands to MCInst.
3358/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3359/// when they refer multiple MIOperands inside a single one.
3360bool ARMAsmParser::
3361cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3362 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3363 // The second source operand must be the same register as the destination
3364 // operand.
3365 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003366 (((ARMOperand*)Operands[3])->getReg() !=
3367 ((ARMOperand*)Operands[5])->getReg()) &&
3368 (((ARMOperand*)Operands[3])->getReg() !=
3369 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003370 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003371 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003372 return false;
3373 }
3374 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3375 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003376 // If we have a three-operand form, make sure to set Rn to be the operand
3377 // that isn't the same as Rd.
3378 unsigned RegOp = 4;
3379 if (Operands.size() == 6 &&
3380 ((ARMOperand*)Operands[4])->getReg() ==
3381 ((ARMOperand*)Operands[3])->getReg())
3382 RegOp = 5;
3383 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3384 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003385 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3386
3387 return true;
3388}
Jim Grosbach623a4542011-08-10 22:42:16 +00003389
Jim Grosbach12431322011-10-24 22:16:58 +00003390bool ARMAsmParser::
3391cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3392 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3393 // Vd
3394 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3395 // Create a writeback register dummy placeholder.
3396 Inst.addOperand(MCOperand::CreateImm(0));
3397 // Vn
3398 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3399 // pred
3400 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3401 return true;
3402}
3403
3404bool ARMAsmParser::
3405cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3406 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3407 // Vd
3408 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3409 // Create a writeback register dummy placeholder.
3410 Inst.addOperand(MCOperand::CreateImm(0));
3411 // Vn
3412 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3413 // Vm
3414 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3415 // pred
3416 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3417 return true;
3418}
3419
Jim Grosbach4334e032011-10-31 21:50:31 +00003420bool ARMAsmParser::
3421cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3422 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3423 // Create a writeback register dummy placeholder.
3424 Inst.addOperand(MCOperand::CreateImm(0));
3425 // Vn
3426 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3427 // Vt
3428 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3429 // pred
3430 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3431 return true;
3432}
3433
3434bool ARMAsmParser::
3435cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3436 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3437 // Create a writeback register dummy placeholder.
3438 Inst.addOperand(MCOperand::CreateImm(0));
3439 // Vn
3440 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3441 // Vm
3442 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3443 // Vt
3444 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3445 // pred
3446 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3447 return true;
3448}
3449
Bill Wendlinge7176102010-11-06 22:36:58 +00003450/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003451/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003452bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003453parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003454 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003455 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003456 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003457 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003458 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003459
Sean Callanan18b83232010-01-19 21:44:56 +00003460 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003461 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003462 if (BaseRegNum == -1)
3463 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003464
Daniel Dunbar05710932011-01-18 05:34:17 +00003465 // The next token must either be a comma or a closing bracket.
3466 const AsmToken &Tok = Parser.getTok();
3467 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003468 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003469
Jim Grosbach7ce05792011-08-03 23:50:40 +00003470 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003471 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003472 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003473
Jim Grosbach7ce05792011-08-03 23:50:40 +00003474 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003475 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003476
Jim Grosbachfb12f352011-09-19 18:42:21 +00003477 // If there's a pre-indexing writeback marker, '!', just add it as a token
3478 // operand. It's rather odd, but syntactically valid.
3479 if (Parser.getTok().is(AsmToken::Exclaim)) {
3480 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3481 Parser.Lex(); // Eat the '!'.
3482 }
3483
Jim Grosbach7ce05792011-08-03 23:50:40 +00003484 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003485 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003486
Jim Grosbach7ce05792011-08-03 23:50:40 +00003487 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3488 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003489
Jim Grosbach57dcb852011-10-11 17:29:55 +00003490 // If we have a ':', it's an alignment specifier.
3491 if (Parser.getTok().is(AsmToken::Colon)) {
3492 Parser.Lex(); // Eat the ':'.
3493 E = Parser.getTok().getLoc();
3494
3495 const MCExpr *Expr;
3496 if (getParser().ParseExpression(Expr))
3497 return true;
3498
3499 // The expression has to be a constant. Memory references with relocations
3500 // don't come through here, as they use the <label> forms of the relevant
3501 // instructions.
3502 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3503 if (!CE)
3504 return Error (E, "constant expression expected");
3505
3506 unsigned Align = 0;
3507 switch (CE->getValue()) {
3508 default:
3509 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3510 case 64: Align = 8; break;
3511 case 128: Align = 16; break;
3512 case 256: Align = 32; break;
3513 }
3514
3515 // Now we should have the closing ']'
3516 E = Parser.getTok().getLoc();
3517 if (Parser.getTok().isNot(AsmToken::RBrac))
3518 return Error(E, "']' expected");
3519 Parser.Lex(); // Eat right bracket token.
3520
3521 // Don't worry about range checking the value here. That's handled by
3522 // the is*() predicates.
3523 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3524 ARM_AM::no_shift, 0, Align,
3525 false, S, E));
3526
3527 // If there's a pre-indexing writeback marker, '!', just add it as a token
3528 // operand.
3529 if (Parser.getTok().is(AsmToken::Exclaim)) {
3530 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3531 Parser.Lex(); // Eat the '!'.
3532 }
3533
3534 return false;
3535 }
3536
3537 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003538 // offset.
3539 if (Parser.getTok().is(AsmToken::Hash)) {
3540 Parser.Lex(); // Eat the '#'.
3541 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003542
Owen Anderson0da10cf2011-08-29 19:36:44 +00003543 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003544 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003545 if (getParser().ParseExpression(Offset))
3546 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003547
3548 // The expression has to be a constant. Memory references with relocations
3549 // don't come through here, as they use the <label> forms of the relevant
3550 // instructions.
3551 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3552 if (!CE)
3553 return Error (E, "constant expression expected");
3554
Owen Anderson0da10cf2011-08-29 19:36:44 +00003555 // If the constant was #-0, represent it as INT32_MIN.
3556 int32_t Val = CE->getValue();
3557 if (isNegative && Val == 0)
3558 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3559
Jim Grosbach7ce05792011-08-03 23:50:40 +00003560 // Now we should have the closing ']'
3561 E = Parser.getTok().getLoc();
3562 if (Parser.getTok().isNot(AsmToken::RBrac))
3563 return Error(E, "']' expected");
3564 Parser.Lex(); // Eat right bracket token.
3565
3566 // Don't worry about range checking the value here. That's handled by
3567 // the is*() predicates.
3568 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003569 ARM_AM::no_shift, 0, 0,
3570 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003571
3572 // If there's a pre-indexing writeback marker, '!', just add it as a token
3573 // operand.
3574 if (Parser.getTok().is(AsmToken::Exclaim)) {
3575 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3576 Parser.Lex(); // Eat the '!'.
3577 }
3578
3579 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003580 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003581
3582 // The register offset is optionally preceded by a '+' or '-'
3583 bool isNegative = false;
3584 if (Parser.getTok().is(AsmToken::Minus)) {
3585 isNegative = true;
3586 Parser.Lex(); // Eat the '-'.
3587 } else if (Parser.getTok().is(AsmToken::Plus)) {
3588 // Nothing to do.
3589 Parser.Lex(); // Eat the '+'.
3590 }
3591
3592 E = Parser.getTok().getLoc();
3593 int OffsetRegNum = tryParseRegister();
3594 if (OffsetRegNum == -1)
3595 return Error(E, "register expected");
3596
3597 // If there's a shift operator, handle it.
3598 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003599 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003600 if (Parser.getTok().is(AsmToken::Comma)) {
3601 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003602 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003603 return true;
3604 }
3605
3606 // Now we should have the closing ']'
3607 E = Parser.getTok().getLoc();
3608 if (Parser.getTok().isNot(AsmToken::RBrac))
3609 return Error(E, "']' expected");
3610 Parser.Lex(); // Eat right bracket token.
3611
3612 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003613 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003614 S, E));
3615
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003616 // If there's a pre-indexing writeback marker, '!', just add it as a token
3617 // operand.
3618 if (Parser.getTok().is(AsmToken::Exclaim)) {
3619 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3620 Parser.Lex(); // Eat the '!'.
3621 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003622
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003623 return false;
3624}
3625
Jim Grosbach7ce05792011-08-03 23:50:40 +00003626/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003627/// ( lsl | lsr | asr | ror ) , # shift_amount
3628/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003629/// return true if it parses a shift otherwise it returns false.
3630bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3631 unsigned &Amount) {
3632 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003633 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003634 if (Tok.isNot(AsmToken::Identifier))
3635 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003636 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003637 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003638 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003639 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003640 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003641 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003642 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003643 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003644 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003645 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003646 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003647 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003648 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003649 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003650
Jim Grosbach7ce05792011-08-03 23:50:40 +00003651 // rrx stands alone.
3652 Amount = 0;
3653 if (St != ARM_AM::rrx) {
3654 Loc = Parser.getTok().getLoc();
3655 // A '#' and a shift amount.
3656 const AsmToken &HashTok = Parser.getTok();
3657 if (HashTok.isNot(AsmToken::Hash))
3658 return Error(HashTok.getLoc(), "'#' expected");
3659 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003660
Jim Grosbach7ce05792011-08-03 23:50:40 +00003661 const MCExpr *Expr;
3662 if (getParser().ParseExpression(Expr))
3663 return true;
3664 // Range check the immediate.
3665 // lsl, ror: 0 <= imm <= 31
3666 // lsr, asr: 0 <= imm <= 32
3667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3668 if (!CE)
3669 return Error(Loc, "shift amount must be an immediate");
3670 int64_t Imm = CE->getValue();
3671 if (Imm < 0 ||
3672 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3673 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3674 return Error(Loc, "immediate shift value out of range");
3675 Amount = Imm;
3676 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003677
3678 return false;
3679}
3680
Jim Grosbach9d390362011-10-03 23:38:36 +00003681/// parseFPImm - A floating point immediate expression operand.
3682ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3683parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3684 SMLoc S = Parser.getTok().getLoc();
3685
3686 if (Parser.getTok().isNot(AsmToken::Hash))
3687 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003688
3689 // Disambiguate the VMOV forms that can accept an FP immediate.
3690 // vmov.f32 <sreg>, #imm
3691 // vmov.f64 <dreg>, #imm
3692 // vmov.f32 <dreg>, #imm @ vector f32x2
3693 // vmov.f32 <qreg>, #imm @ vector f32x4
3694 //
3695 // There are also the NEON VMOV instructions which expect an
3696 // integer constant. Make sure we don't try to parse an FPImm
3697 // for these:
3698 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3699 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3700 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3701 TyOp->getToken() != ".f64"))
3702 return MatchOperand_NoMatch;
3703
Jim Grosbach9d390362011-10-03 23:38:36 +00003704 Parser.Lex(); // Eat the '#'.
3705
3706 // Handle negation, as that still comes through as a separate token.
3707 bool isNegative = false;
3708 if (Parser.getTok().is(AsmToken::Minus)) {
3709 isNegative = true;
3710 Parser.Lex();
3711 }
3712 const AsmToken &Tok = Parser.getTok();
3713 if (Tok.is(AsmToken::Real)) {
3714 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3715 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3716 // If we had a '-' in front, toggle the sign bit.
3717 IntVal ^= (uint64_t)isNegative << 63;
3718 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3719 Parser.Lex(); // Eat the token.
3720 if (Val == -1) {
3721 TokError("floating point value out of range");
3722 return MatchOperand_ParseFail;
3723 }
3724 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3725 return MatchOperand_Success;
3726 }
3727 if (Tok.is(AsmToken::Integer)) {
3728 int64_t Val = Tok.getIntVal();
3729 Parser.Lex(); // Eat the token.
3730 if (Val > 255 || Val < 0) {
3731 TokError("encoded floating point value out of range");
3732 return MatchOperand_ParseFail;
3733 }
3734 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3735 return MatchOperand_Success;
3736 }
3737
3738 TokError("invalid floating point immediate");
3739 return MatchOperand_ParseFail;
3740}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003741/// Parse a arm instruction operand. For now this parses the operand regardless
3742/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003743bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003744 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003745 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003746
3747 // Check if the current operand has a custom associated parser, if so, try to
3748 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003749 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3750 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003751 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003752 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3753 // there was a match, but an error occurred, in which case, just return that
3754 // the operand parsing failed.
3755 if (ResTy == MatchOperand_ParseFail)
3756 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003757
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003758 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003759 default:
3760 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003761 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003762 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003763 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003764 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003765 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003766 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003767 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003768 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003769 else if (Res == -1) // irrecoverable error
3770 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003771 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3772 S = Parser.getTok().getLoc();
3773 Parser.Lex();
3774 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3775 return false;
3776 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003777
3778 // Fall though for the Identifier case that is not a register or a
3779 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003780 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003781 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003782 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003783 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003784 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003785 // This was not a register so parse other operands that start with an
3786 // identifier (like labels) as expressions and create them as immediates.
3787 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003788 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003789 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003790 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003791 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003792 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3793 return false;
3794 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003795 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003796 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003797 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003798 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003799 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003800 // #42 -> immediate.
3801 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003802 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003803 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003804 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003805 const MCExpr *ImmVal;
3806 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003807 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003809 if (CE) {
3810 int32_t Val = CE->getValue();
3811 if (isNegative && Val == 0)
3812 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003813 }
Sean Callanan76264762010-04-02 22:27:05 +00003814 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003815 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3816 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003817 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003818 case AsmToken::Colon: {
3819 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003820 // FIXME: Check it's an expression prefix,
3821 // e.g. (FOO - :lower16:BAR) isn't legal.
3822 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003823 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003824 return true;
3825
Evan Cheng75972122011-01-13 07:58:56 +00003826 const MCExpr *SubExprVal;
3827 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003828 return true;
3829
Evan Cheng75972122011-01-13 07:58:56 +00003830 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3831 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003832 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003833 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003834 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003835 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003836 }
3837}
3838
Jim Grosbach1355cf12011-07-26 17:10:22 +00003839// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003840// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003841bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003842 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003843
3844 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003845 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003846 Parser.Lex(); // Eat ':'
3847
3848 if (getLexer().isNot(AsmToken::Identifier)) {
3849 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3850 return true;
3851 }
3852
3853 StringRef IDVal = Parser.getTok().getIdentifier();
3854 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003855 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003856 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003857 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003858 } else {
3859 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3860 return true;
3861 }
3862 Parser.Lex();
3863
3864 if (getLexer().isNot(AsmToken::Colon)) {
3865 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3866 return true;
3867 }
3868 Parser.Lex(); // Eat the last ':'
3869 return false;
3870}
3871
Daniel Dunbar352e1482011-01-11 15:59:50 +00003872/// \brief Given a mnemonic, split out possible predication code and carry
3873/// setting letters to form a canonical mnemonic and flags.
3874//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003875// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003876// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003877StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003878 unsigned &PredicationCode,
3879 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003880 unsigned &ProcessorIMod,
3881 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003882 PredicationCode = ARMCC::AL;
3883 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003884 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003885
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003886 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003887 //
3888 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003889 if ((Mnemonic == "movs" && isThumb()) ||
3890 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3891 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3892 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3893 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3894 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3895 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3896 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003897 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003898
Jim Grosbach3f00e312011-07-11 17:09:57 +00003899 // First, split out any predication code. Ignore mnemonics we know aren't
3900 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003901 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003902 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003903 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003904 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003905 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3906 .Case("eq", ARMCC::EQ)
3907 .Case("ne", ARMCC::NE)
3908 .Case("hs", ARMCC::HS)
3909 .Case("cs", ARMCC::HS)
3910 .Case("lo", ARMCC::LO)
3911 .Case("cc", ARMCC::LO)
3912 .Case("mi", ARMCC::MI)
3913 .Case("pl", ARMCC::PL)
3914 .Case("vs", ARMCC::VS)
3915 .Case("vc", ARMCC::VC)
3916 .Case("hi", ARMCC::HI)
3917 .Case("ls", ARMCC::LS)
3918 .Case("ge", ARMCC::GE)
3919 .Case("lt", ARMCC::LT)
3920 .Case("gt", ARMCC::GT)
3921 .Case("le", ARMCC::LE)
3922 .Case("al", ARMCC::AL)
3923 .Default(~0U);
3924 if (CC != ~0U) {
3925 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3926 PredicationCode = CC;
3927 }
Bill Wendling52925b62010-10-29 23:50:21 +00003928 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003929
Daniel Dunbar352e1482011-01-11 15:59:50 +00003930 // Next, determine if we have a carry setting bit. We explicitly ignore all
3931 // the instructions we know end in 's'.
3932 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003933 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003934 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3935 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3936 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003937 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3938 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003939 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3940 CarrySetting = true;
3941 }
3942
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003943 // The "cps" instruction can have a interrupt mode operand which is glued into
3944 // the mnemonic. Check if this is the case, split it and parse the imod op
3945 if (Mnemonic.startswith("cps")) {
3946 // Split out any imod code.
3947 unsigned IMod =
3948 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3949 .Case("ie", ARM_PROC::IE)
3950 .Case("id", ARM_PROC::ID)
3951 .Default(~0U);
3952 if (IMod != ~0U) {
3953 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3954 ProcessorIMod = IMod;
3955 }
3956 }
3957
Jim Grosbach89df9962011-08-26 21:43:41 +00003958 // The "it" instruction has the condition mask on the end of the mnemonic.
3959 if (Mnemonic.startswith("it")) {
3960 ITMask = Mnemonic.slice(2, Mnemonic.size());
3961 Mnemonic = Mnemonic.slice(0, 2);
3962 }
3963
Daniel Dunbar352e1482011-01-11 15:59:50 +00003964 return Mnemonic;
3965}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003966
3967/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3968/// inclusion of carry set or predication code operands.
3969//
3970// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003971void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003972getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003973 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003974 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3975 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003976 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003977 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003978 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003979 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003980 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003981 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003982 Mnemonic == "mla" || Mnemonic == "smlal" ||
3983 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003984 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003985 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003986 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003987
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003988 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3989 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3990 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3991 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003992 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3993 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003994 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003995 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3996 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3997 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003998 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3999 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004000 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004001 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004002 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004003 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004004
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004005 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004006 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004007 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004008 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004009 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004010}
4011
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004012bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4013 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004014 // FIXME: This is all horribly hacky. We really need a better way to deal
4015 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004016
4017 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4018 // another does not. Specifically, the MOVW instruction does not. So we
4019 // special case it here and remove the defaulted (non-setting) cc_out
4020 // operand if that's the instruction we're trying to match.
4021 //
4022 // We do this as post-processing of the explicit operands rather than just
4023 // conditionally adding the cc_out in the first place because we need
4024 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004025 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004026 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4027 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4028 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4029 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004030
4031 // Register-register 'add' for thumb does not have a cc_out operand
4032 // when there are only two register operands.
4033 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4034 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4035 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4036 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4037 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004038 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004039 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4040 // have to check the immediate range here since Thumb2 has a variant
4041 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004042 if (((isThumb() && Mnemonic == "add") ||
4043 (isThumbTwo() && Mnemonic == "sub")) &&
4044 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004045 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4046 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4047 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004048 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4049 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4050 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004051 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004052 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4053 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004054 // selecting via the generic "add" mnemonic, so to know that we
4055 // should remove the cc_out operand, we have to explicitly check that
4056 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004057 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4058 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004059 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4060 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4061 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4062 // Nest conditions rather than one big 'if' statement for readability.
4063 //
4064 // If either register is a high reg, it's either one of the SP
4065 // variants (handled above) or a 32-bit encoding, so we just
4066 // check against T3.
4067 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4068 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4069 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4070 return false;
4071 // If both registers are low, we're in an IT block, and the immediate is
4072 // in range, we should use encoding T1 instead, which has a cc_out.
4073 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004074 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004075 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4076 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4077 return false;
4078
4079 // Otherwise, we use encoding T4, which does not have a cc_out
4080 // operand.
4081 return true;
4082 }
4083
Jim Grosbach64944f42011-09-14 21:00:40 +00004084 // The thumb2 multiply instruction doesn't have a CCOut register, so
4085 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4086 // use the 16-bit encoding or not.
4087 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4088 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4089 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4090 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4091 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4092 // If the registers aren't low regs, the destination reg isn't the
4093 // same as one of the source regs, or the cc_out operand is zero
4094 // outside of an IT block, we have to use the 32-bit encoding, so
4095 // remove the cc_out operand.
4096 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4097 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4098 !inITBlock() ||
4099 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4100 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4101 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4102 static_cast<ARMOperand*>(Operands[4])->getReg())))
4103 return true;
4104
4105
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004106
Jim Grosbachf69c8042011-08-24 21:42:27 +00004107 // Register-register 'add/sub' for thumb does not have a cc_out operand
4108 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4109 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4110 // right, this will result in better diagnostics (which operand is off)
4111 // anyway.
4112 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4113 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004114 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4115 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4116 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4117 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004118
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004119 return false;
4120}
4121
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004122static bool isDataTypeToken(StringRef Tok) {
4123 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4124 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4125 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4126 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4127 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4128 Tok == ".f" || Tok == ".d";
4129}
4130
4131// FIXME: This bit should probably be handled via an explicit match class
4132// in the .td files that matches the suffix instead of having it be
4133// a literal string token the way it is now.
4134static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4135 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4136}
4137
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004138/// Parse an arm instruction mnemonic followed by its operands.
4139bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4140 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4141 // Create the leading tokens for the mnemonic, split by '.' characters.
4142 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004143 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004144
Daniel Dunbar352e1482011-01-11 15:59:50 +00004145 // Split out the predication code and carry setting flag from the mnemonic.
4146 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004147 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004148 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004149 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004150 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004151 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004152
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004153 // In Thumb1, only the branch (B) instruction can be predicated.
4154 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4155 Parser.EatToEndOfStatement();
4156 return Error(NameLoc, "conditional execution not supported in Thumb1");
4157 }
4158
Jim Grosbachffa32252011-07-19 19:13:28 +00004159 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4160
Jim Grosbach89df9962011-08-26 21:43:41 +00004161 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4162 // is the mask as it will be for the IT encoding if the conditional
4163 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4164 // where the conditional bit0 is zero, the instruction post-processing
4165 // will adjust the mask accordingly.
4166 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004167 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4168 if (ITMask.size() > 3) {
4169 Parser.EatToEndOfStatement();
4170 return Error(Loc, "too many conditions on IT instruction");
4171 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004172 unsigned Mask = 8;
4173 for (unsigned i = ITMask.size(); i != 0; --i) {
4174 char pos = ITMask[i - 1];
4175 if (pos != 't' && pos != 'e') {
4176 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004177 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004178 }
4179 Mask >>= 1;
4180 if (ITMask[i - 1] == 't')
4181 Mask |= 8;
4182 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004183 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004184 }
4185
Jim Grosbachffa32252011-07-19 19:13:28 +00004186 // FIXME: This is all a pretty gross hack. We should automatically handle
4187 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004188
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004189 // Next, add the CCOut and ConditionCode operands, if needed.
4190 //
4191 // For mnemonics which can ever incorporate a carry setting bit or predication
4192 // code, our matching model involves us always generating CCOut and
4193 // ConditionCode operands to match the mnemonic "as written" and then we let
4194 // the matcher deal with finding the right instruction or generating an
4195 // appropriate error.
4196 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004197 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004198
Jim Grosbach33c16a22011-07-14 22:04:21 +00004199 // If we had a carry-set on an instruction that can't do that, issue an
4200 // error.
4201 if (!CanAcceptCarrySet && CarrySetting) {
4202 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004203 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004204 "' can not set flags, but 's' suffix specified");
4205 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004206 // If we had a predication code on an instruction that can't do that, issue an
4207 // error.
4208 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4209 Parser.EatToEndOfStatement();
4210 return Error(NameLoc, "instruction '" + Mnemonic +
4211 "' is not predicable, but condition code specified");
4212 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004213
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004214 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004215 if (CanAcceptCarrySet) {
4216 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004217 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004218 Loc));
4219 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004220
4221 // Add the predication code operand, if necessary.
4222 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004223 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4224 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004225 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004226 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004227 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004228
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004229 // Add the processor imod operand, if necessary.
4230 if (ProcessorIMod) {
4231 Operands.push_back(ARMOperand::CreateImm(
4232 MCConstantExpr::Create(ProcessorIMod, getContext()),
4233 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004234 }
4235
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004236 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004237 while (Next != StringRef::npos) {
4238 Start = Next;
4239 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004240 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004241
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004242 // Some NEON instructions have an optional datatype suffix that is
4243 // completely ignored. Check for that.
4244 if (isDataTypeToken(ExtraToken) &&
4245 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4246 continue;
4247
Jim Grosbach81d2e392011-09-07 16:06:04 +00004248 if (ExtraToken != ".n") {
4249 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4250 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4251 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004252 }
4253
4254 // Read the remaining operands.
4255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004256 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004257 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004258 Parser.EatToEndOfStatement();
4259 return true;
4260 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004261
4262 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004263 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004264
4265 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004266 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004267 Parser.EatToEndOfStatement();
4268 return true;
4269 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004270 }
4271 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004272
Chris Lattnercbf8a982010-09-11 16:18:25 +00004273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004274 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004275 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004276 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004277 }
Bill Wendling146018f2010-11-06 21:42:12 +00004278
Chris Lattner34e53142010-09-08 05:10:46 +00004279 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004280
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004281 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4282 // do and don't have a cc_out optional-def operand. With some spot-checks
4283 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004284 // parse and adjust accordingly before actually matching. We shouldn't ever
4285 // try to remove a cc_out operand that was explicitly set on the the
4286 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4287 // table driven matcher doesn't fit well with the ARM instruction set.
4288 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004289 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4290 Operands.erase(Operands.begin() + 1);
4291 delete Op;
4292 }
4293
Jim Grosbachcf121c32011-07-28 21:57:55 +00004294 // ARM mode 'blx' need special handling, as the register operand version
4295 // is predicable, but the label operand version is not. So, we can't rely
4296 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004297 // a k_CondCode operand in the list. If we're trying to match the label
4298 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004299 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4300 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4301 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4302 Operands.erase(Operands.begin() + 1);
4303 delete Op;
4304 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004305
4306 // The vector-compare-to-zero instructions have a literal token "#0" at
4307 // the end that comes to here as an immediate operand. Convert it to a
4308 // token to play nicely with the matcher.
4309 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4310 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4311 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4312 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4313 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4314 if (CE && CE->getValue() == 0) {
4315 Operands.erase(Operands.begin() + 5);
4316 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4317 delete Op;
4318 }
4319 }
Jim Grosbach68259142011-10-03 22:30:24 +00004320 // VCMP{E} does the same thing, but with a different operand count.
4321 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4322 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4323 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4324 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4325 if (CE && CE->getValue() == 0) {
4326 Operands.erase(Operands.begin() + 4);
4327 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4328 delete Op;
4329 }
4330 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004331 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4332 // end. Convert it to a token here.
4333 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4334 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4335 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4336 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4337 if (CE && CE->getValue() == 0) {
4338 Operands.erase(Operands.begin() + 5);
4339 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4340 delete Op;
4341 }
4342 }
4343
Chris Lattner98986712010-01-14 22:21:20 +00004344 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004345}
4346
Jim Grosbach189610f2011-07-26 18:25:39 +00004347// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004348
4349// return 'true' if register list contains non-low GPR registers,
4350// 'false' otherwise. If Reg is in the register list or is HiReg, set
4351// 'containsReg' to true.
4352static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4353 unsigned HiReg, bool &containsReg) {
4354 containsReg = false;
4355 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4356 unsigned OpReg = Inst.getOperand(i).getReg();
4357 if (OpReg == Reg)
4358 containsReg = true;
4359 // Anything other than a low register isn't legal here.
4360 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4361 return true;
4362 }
4363 return false;
4364}
4365
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004366// Check if the specified regisgter is in the register list of the inst,
4367// starting at the indicated operand number.
4368static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4369 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4370 unsigned OpReg = Inst.getOperand(i).getReg();
4371 if (OpReg == Reg)
4372 return true;
4373 }
4374 return false;
4375}
4376
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004377// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4378// the ARMInsts array) instead. Getting that here requires awkward
4379// API changes, though. Better way?
4380namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004381extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004382}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004383static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004384 return ARMInsts[Opcode];
4385}
4386
Jim Grosbach189610f2011-07-26 18:25:39 +00004387// FIXME: We would really like to be able to tablegen'erate this.
4388bool ARMAsmParser::
4389validateInstruction(MCInst &Inst,
4390 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004391 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004392 SMLoc Loc = Operands[0]->getStartLoc();
4393 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004394 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4395 // being allowed in IT blocks, but not being predicable. It just always
4396 // executes.
4397 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004398 unsigned bit = 1;
4399 if (ITState.FirstCond)
4400 ITState.FirstCond = false;
4401 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004402 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004403 // The instruction must be predicable.
4404 if (!MCID.isPredicable())
4405 return Error(Loc, "instructions in IT block must be predicable");
4406 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4407 unsigned ITCond = bit ? ITState.Cond :
4408 ARMCC::getOppositeCondition(ITState.Cond);
4409 if (Cond != ITCond) {
4410 // Find the condition code Operand to get its SMLoc information.
4411 SMLoc CondLoc;
4412 for (unsigned i = 1; i < Operands.size(); ++i)
4413 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4414 CondLoc = Operands[i]->getStartLoc();
4415 return Error(CondLoc, "incorrect condition in IT block; got '" +
4416 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4417 "', but expected '" +
4418 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4419 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004420 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004421 } else if (isThumbTwo() && MCID.isPredicable() &&
4422 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004423 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4424 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004425 return Error(Loc, "predicated instructions must be in IT block");
4426
Jim Grosbach189610f2011-07-26 18:25:39 +00004427 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004428 case ARM::LDRD:
4429 case ARM::LDRD_PRE:
4430 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004431 case ARM::LDREXD: {
4432 // Rt2 must be Rt + 1.
4433 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4434 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4435 if (Rt2 != Rt + 1)
4436 return Error(Operands[3]->getStartLoc(),
4437 "destination operands must be sequential");
4438 return false;
4439 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004440 case ARM::STRD: {
4441 // Rt2 must be Rt + 1.
4442 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4443 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4444 if (Rt2 != Rt + 1)
4445 return Error(Operands[3]->getStartLoc(),
4446 "source operands must be sequential");
4447 return false;
4448 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004449 case ARM::STRD_PRE:
4450 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004451 case ARM::STREXD: {
4452 // Rt2 must be Rt + 1.
4453 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4454 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4455 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004456 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004457 "source operands must be sequential");
4458 return false;
4459 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004460 case ARM::SBFX:
4461 case ARM::UBFX: {
4462 // width must be in range [1, 32-lsb]
4463 unsigned lsb = Inst.getOperand(2).getImm();
4464 unsigned widthm1 = Inst.getOperand(3).getImm();
4465 if (widthm1 >= 32 - lsb)
4466 return Error(Operands[5]->getStartLoc(),
4467 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004468 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004469 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004470 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004471 // If we're parsing Thumb2, the .w variant is available and handles
4472 // most cases that are normally illegal for a Thumb1 LDM
4473 // instruction. We'll make the transformation in processInstruction()
4474 // if necessary.
4475 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004476 // Thumb LDM instructions are writeback iff the base register is not
4477 // in the register list.
4478 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004479 bool hasWritebackToken =
4480 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4481 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004482 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004483 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004484 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4485 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004486 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004487 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004488 return Error(Operands[2]->getStartLoc(),
4489 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004490 // If we should not have writeback, there must not be a '!'. This is
4491 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004492 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004493 return Error(Operands[3]->getStartLoc(),
4494 "writeback operator '!' not allowed when base register "
4495 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004496
4497 break;
4498 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004499 case ARM::t2LDMIA_UPD: {
4500 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4501 return Error(Operands[4]->getStartLoc(),
4502 "writeback operator '!' not allowed when base register "
4503 "in register list");
4504 break;
4505 }
Jim Grosbach54026372011-11-10 23:17:11 +00004506 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4507 // so only issue a diagnostic for thumb1. The instructions will be
4508 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004509 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004510 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004511 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4512 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004513 return Error(Operands[2]->getStartLoc(),
4514 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004515 break;
4516 }
4517 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004518 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004519 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4520 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004521 return Error(Operands[2]->getStartLoc(),
4522 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004523 break;
4524 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004525 case ARM::tSTMIA_UPD: {
4526 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004527 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004528 return Error(Operands[4]->getStartLoc(),
4529 "registers must be in range r0-r7");
4530 break;
4531 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004532 }
4533
4534 return false;
4535}
4536
Jim Grosbach83ec8772011-11-10 23:42:14 +00004537bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004538processInstruction(MCInst &Inst,
4539 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4540 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004541 // Handle the MOV complex aliases.
Jim Grosbachee10ff82011-11-10 19:18:01 +00004542 case ARM::ASRi:
4543 case ARM::LSRi:
4544 case ARM::LSLi:
4545 case ARM::RORi: {
4546 ARM_AM::ShiftOpc ShiftTy;
4547 unsigned Amt = Inst.getOperand(2).getImm();
4548 switch(Inst.getOpcode()) {
4549 default: llvm_unreachable("unexpected opcode!");
4550 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4551 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4552 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4553 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4554 }
4555 // A shift by zero is a plain MOVr, not a MOVsi.
4556 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4557 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004558 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004559 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004560 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4561 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004562 if (Opc == ARM::MOVsi)
4563 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004564 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4565 TmpInst.addOperand(Inst.getOperand(4));
4566 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4567 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004568 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004569 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004570 case ARM::t2LDMIA_UPD: {
4571 // If this is a load of a single register, then we should use
4572 // a post-indexed LDR instruction instead, per the ARM ARM.
4573 if (Inst.getNumOperands() != 5)
4574 return false;
4575 MCInst TmpInst;
4576 TmpInst.setOpcode(ARM::t2LDR_POST);
4577 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4578 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4579 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4580 TmpInst.addOperand(MCOperand::CreateImm(4));
4581 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4582 TmpInst.addOperand(Inst.getOperand(3));
4583 Inst = TmpInst;
4584 return true;
4585 }
4586 case ARM::t2STMDB_UPD: {
4587 // If this is a store of a single register, then we should use
4588 // a pre-indexed STR instruction instead, per the ARM ARM.
4589 if (Inst.getNumOperands() != 5)
4590 return false;
4591 MCInst TmpInst;
4592 TmpInst.setOpcode(ARM::t2STR_PRE);
4593 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4594 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4595 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4596 TmpInst.addOperand(MCOperand::CreateImm(-4));
4597 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4598 TmpInst.addOperand(Inst.getOperand(3));
4599 Inst = TmpInst;
4600 return true;
4601 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004602 case ARM::LDMIA_UPD:
4603 // If this is a load of a single register via a 'pop', then we should use
4604 // a post-indexed LDR instruction instead, per the ARM ARM.
4605 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4606 Inst.getNumOperands() == 5) {
4607 MCInst TmpInst;
4608 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4609 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4610 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4611 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4612 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4613 TmpInst.addOperand(MCOperand::CreateImm(4));
4614 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4615 TmpInst.addOperand(Inst.getOperand(3));
4616 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004617 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004618 }
4619 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004620 case ARM::STMDB_UPD:
4621 // If this is a store of a single register via a 'push', then we should use
4622 // a pre-indexed STR instruction instead, per the ARM ARM.
4623 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4624 Inst.getNumOperands() == 5) {
4625 MCInst TmpInst;
4626 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4627 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4628 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4629 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4630 TmpInst.addOperand(MCOperand::CreateImm(-4));
4631 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4632 TmpInst.addOperand(Inst.getOperand(3));
4633 Inst = TmpInst;
4634 }
4635 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004636 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004637 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4638 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4639 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4640 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004641 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004642 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004643 return true;
4644 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004645 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004646 case ARM::tSUBi8:
4647 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4648 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4649 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4650 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004651 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004652 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004653 return true;
4654 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004655 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004656 case ARM::tB:
4657 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004658 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004659 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004660 return true;
4661 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004662 break;
4663 case ARM::t2B:
4664 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004665 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004666 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004667 return true;
4668 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004669 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004670 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004671 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004672 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004673 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004674 return true;
4675 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004676 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004677 case ARM::tBcc:
4678 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004679 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004680 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004681 return true;
4682 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004683 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004684 case ARM::tLDMIA: {
4685 // If the register list contains any high registers, or if the writeback
4686 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4687 // instead if we're in Thumb2. Otherwise, this should have generated
4688 // an error in validateInstruction().
4689 unsigned Rn = Inst.getOperand(0).getReg();
4690 bool hasWritebackToken =
4691 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4692 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4693 bool listContainsBase;
4694 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4695 (!listContainsBase && !hasWritebackToken) ||
4696 (listContainsBase && hasWritebackToken)) {
4697 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4698 assert (isThumbTwo());
4699 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4700 // If we're switching to the updating version, we need to insert
4701 // the writeback tied operand.
4702 if (hasWritebackToken)
4703 Inst.insert(Inst.begin(),
4704 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004705 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004706 }
4707 break;
4708 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004709 case ARM::tSTMIA_UPD: {
4710 // If the register list contains any high registers, we need to use
4711 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4712 // should have generated an error in validateInstruction().
4713 unsigned Rn = Inst.getOperand(0).getReg();
4714 bool listContainsBase;
4715 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4716 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4717 assert (isThumbTwo());
4718 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004719 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004720 }
4721 break;
4722 }
Jim Grosbach54026372011-11-10 23:17:11 +00004723 case ARM::tPOP: {
4724 bool listContainsBase;
4725 // If the register list contains any high registers, we need to use
4726 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4727 // should have generated an error in validateInstruction().
4728 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004729 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004730 assert (isThumbTwo());
4731 Inst.setOpcode(ARM::t2LDMIA_UPD);
4732 // Add the base register and writeback operands.
4733 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4734 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004735 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004736 }
4737 case ARM::tPUSH: {
4738 bool listContainsBase;
4739 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004740 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004741 assert (isThumbTwo());
4742 Inst.setOpcode(ARM::t2STMDB_UPD);
4743 // Add the base register and writeback operands.
4744 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4745 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004746 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004747 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004748 case ARM::t2MOVi: {
4749 // If we can use the 16-bit encoding and the user didn't explicitly
4750 // request the 32-bit variant, transform it here.
4751 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4752 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004753 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4754 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4755 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004756 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4757 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4758 // The operands aren't in the same order for tMOVi8...
4759 MCInst TmpInst;
4760 TmpInst.setOpcode(ARM::tMOVi8);
4761 TmpInst.addOperand(Inst.getOperand(0));
4762 TmpInst.addOperand(Inst.getOperand(4));
4763 TmpInst.addOperand(Inst.getOperand(1));
4764 TmpInst.addOperand(Inst.getOperand(2));
4765 TmpInst.addOperand(Inst.getOperand(3));
4766 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004767 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004768 }
4769 break;
4770 }
4771 case ARM::t2MOVr: {
4772 // If we can use the 16-bit encoding and the user didn't explicitly
4773 // request the 32-bit variant, transform it here.
4774 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4775 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4776 Inst.getOperand(2).getImm() == ARMCC::AL &&
4777 Inst.getOperand(4).getReg() == ARM::CPSR &&
4778 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4779 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4780 // The operands aren't the same for tMOV[S]r... (no cc_out)
4781 MCInst TmpInst;
4782 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4783 TmpInst.addOperand(Inst.getOperand(0));
4784 TmpInst.addOperand(Inst.getOperand(1));
4785 TmpInst.addOperand(Inst.getOperand(2));
4786 TmpInst.addOperand(Inst.getOperand(3));
4787 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004788 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004789 }
4790 break;
4791 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004792 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004793 case ARM::t2SXTB:
4794 case ARM::t2UXTH:
4795 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004796 // If we can use the 16-bit encoding and the user didn't explicitly
4797 // request the 32-bit variant, transform it here.
4798 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4799 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4800 Inst.getOperand(2).getImm() == 0 &&
4801 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4802 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004803 unsigned NewOpc;
4804 switch (Inst.getOpcode()) {
4805 default: llvm_unreachable("Illegal opcode!");
4806 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4807 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4808 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4809 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4810 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004811 // The operands aren't the same for thumb1 (no rotate operand).
4812 MCInst TmpInst;
4813 TmpInst.setOpcode(NewOpc);
4814 TmpInst.addOperand(Inst.getOperand(0));
4815 TmpInst.addOperand(Inst.getOperand(1));
4816 TmpInst.addOperand(Inst.getOperand(3));
4817 TmpInst.addOperand(Inst.getOperand(4));
4818 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004819 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00004820 }
4821 break;
4822 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004823 case ARM::t2IT: {
4824 // The mask bits for all but the first condition are represented as
4825 // the low bit of the condition code value implies 't'. We currently
4826 // always have 1 implies 't', so XOR toggle the bits if the low bit
4827 // of the condition code is zero. The encoding also expects the low
4828 // bit of the condition to be encoded as bit 4 of the mask operand,
4829 // so mask that in if needed
4830 MCOperand &MO = Inst.getOperand(1);
4831 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004832 unsigned OrigMask = Mask;
4833 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004834 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004835 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4836 for (unsigned i = 3; i != TZ; --i)
4837 Mask ^= 1 << i;
4838 } else
4839 Mask |= 0x10;
4840 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004841
4842 // Set up the IT block state according to the IT instruction we just
4843 // matched.
4844 assert(!inITBlock() && "nested IT blocks?!");
4845 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4846 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4847 ITState.CurPosition = 0;
4848 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004849 break;
4850 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004851 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00004852 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004853}
4854
Jim Grosbach47a0d522011-08-16 20:45:50 +00004855unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4856 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4857 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004858 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004859 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004860 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4861 assert(MCID.hasOptionalDef() &&
4862 "optionally flag setting instruction missing optional def operand");
4863 assert(MCID.NumOperands == Inst.getNumOperands() &&
4864 "operand count mismatch!");
4865 // Find the optional-def operand (cc_out).
4866 unsigned OpNo;
4867 for (OpNo = 0;
4868 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4869 ++OpNo)
4870 ;
4871 // If we're parsing Thumb1, reject it completely.
4872 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4873 return Match_MnemonicFail;
4874 // If we're parsing Thumb2, which form is legal depends on whether we're
4875 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004876 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4877 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004878 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004879 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4880 inITBlock())
4881 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004882 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004883 // Some high-register supporting Thumb1 encodings only allow both registers
4884 // to be from r0-r7 when in Thumb2.
4885 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4886 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4887 isARMLowRegister(Inst.getOperand(2).getReg()))
4888 return Match_RequiresThumb2;
4889 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004890 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004891 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4892 isARMLowRegister(Inst.getOperand(1).getReg()))
4893 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004894 return Match_Success;
4895}
4896
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004897bool ARMAsmParser::
4898MatchAndEmitInstruction(SMLoc IDLoc,
4899 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4900 MCStreamer &Out) {
4901 MCInst Inst;
4902 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004903 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004904 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004905 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004906 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004907 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004908 // Context sensitive operand constraints aren't handled by the matcher,
4909 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004910 if (validateInstruction(Inst, Operands)) {
4911 // Still progress the IT block, otherwise one wrong condition causes
4912 // nasty cascading errors.
4913 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004914 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004915 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004916
Jim Grosbachf8fce712011-08-11 17:35:48 +00004917 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00004918 // encoding is selected. Loop on it while changes happen so the
4919 // individual transformations can chain off each other. E.g.,
4920 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
4921 while (processInstruction(Inst, Operands))
4922 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004923
Jim Grosbacha1109882011-09-02 23:22:08 +00004924 // Only move forward at the very end so that everything in validate
4925 // and process gets a consistent answer about whether we're in an IT
4926 // block.
4927 forwardITPosition();
4928
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004929 Out.EmitInstruction(Inst);
4930 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004931 case Match_MissingFeature:
4932 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4933 return true;
4934 case Match_InvalidOperand: {
4935 SMLoc ErrorLoc = IDLoc;
4936 if (ErrorInfo != ~0U) {
4937 if (ErrorInfo >= Operands.size())
4938 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004939
Chris Lattnere73d4f82010-10-28 21:41:58 +00004940 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4941 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4942 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004943
Chris Lattnere73d4f82010-10-28 21:41:58 +00004944 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004945 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004946 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004947 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004948 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004949 // The converter function will have already emited a diagnostic.
4950 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004951 case Match_RequiresNotITBlock:
4952 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004953 case Match_RequiresITBlock:
4954 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004955 case Match_RequiresV6:
4956 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4957 case Match_RequiresThumb2:
4958 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004959 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004960
Eric Christopherc223e2b2010-10-29 09:26:59 +00004961 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004962 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004963}
4964
Jim Grosbach1355cf12011-07-26 17:10:22 +00004965/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004966bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4967 StringRef IDVal = DirectiveID.getIdentifier();
4968 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004969 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004970 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004971 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004972 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004973 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004974 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004975 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004976 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004977 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004978 return true;
4979}
4980
Jim Grosbach1355cf12011-07-26 17:10:22 +00004981/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004982/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004983bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4985 for (;;) {
4986 const MCExpr *Value;
4987 if (getParser().ParseExpression(Value))
4988 return true;
4989
Chris Lattneraaec2052010-01-19 19:46:13 +00004990 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004991
4992 if (getLexer().is(AsmToken::EndOfStatement))
4993 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004994
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004995 // FIXME: Improve diagnostic.
4996 if (getLexer().isNot(AsmToken::Comma))
4997 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004998 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004999 }
5000 }
5001
Sean Callananb9a25b72010-01-19 20:27:46 +00005002 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005003 return false;
5004}
5005
Jim Grosbach1355cf12011-07-26 17:10:22 +00005006/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005007/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005008bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005009 if (getLexer().isNot(AsmToken::EndOfStatement))
5010 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005011 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005012
5013 // TODO: set thumb mode
5014 // TODO: tell the MC streamer the mode
5015 // getParser().getStreamer().Emit???();
5016 return false;
5017}
5018
Jim Grosbach1355cf12011-07-26 17:10:22 +00005019/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005020/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005021bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005022 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5023 bool isMachO = MAI.hasSubsectionsViaSymbols();
5024 StringRef Name;
5025
5026 // Darwin asm has function name after .thumb_func direction
5027 // ELF doesn't
5028 if (isMachO) {
5029 const AsmToken &Tok = Parser.getTok();
5030 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5031 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005032 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005033 Parser.Lex(); // Consume the identifier token.
5034 }
5035
Jim Grosbachd475f862011-11-10 20:48:53 +00005036 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005037 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005038 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005039
Rafael Espindola64695402011-05-16 16:17:21 +00005040 // FIXME: assuming function name will be the line following .thumb_func
5041 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005042 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005043 }
5044
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005045 // Mark symbol as a thumb symbol.
5046 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5047 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005048 return false;
5049}
5050
Jim Grosbach1355cf12011-07-26 17:10:22 +00005051/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005052/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005053bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005054 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005055 if (Tok.isNot(AsmToken::Identifier))
5056 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005057 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005058 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005059 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005060 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005061 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005062 else
5063 return Error(L, "unrecognized syntax mode in .syntax directive");
5064
5065 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005066 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005067 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005068
5069 // TODO tell the MC streamer the mode
5070 // getParser().getStreamer().Emit???();
5071 return false;
5072}
5073
Jim Grosbach1355cf12011-07-26 17:10:22 +00005074/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005075/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005076bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005077 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005078 if (Tok.isNot(AsmToken::Integer))
5079 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005080 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005081 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005082 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005083 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005084 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005085 else
5086 return Error(L, "invalid operand to .code directive");
5087
5088 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005089 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005090 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005091
Evan Cheng32869202011-07-08 22:36:29 +00005092 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005093 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005094 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005095 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005096 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005097 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005098 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005099 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005100 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005101
Kevin Enderby515d5092009-10-15 20:48:48 +00005102 return false;
5103}
5104
Sean Callanan90b70972010-04-07 20:29:34 +00005105extern "C" void LLVMInitializeARMAsmLexer();
5106
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005107/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005108extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005109 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5110 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005111 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005112}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005113
Chris Lattner0692ee62010-09-06 19:11:01 +00005114#define GET_REGISTER_MATCHER
5115#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005116#include "ARMGenAsmMatcher.inc"