blob: 1535a7a77683c68b1a7f68a1be69e9d29089955b [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 Grosbach430052b2011-11-14 17:52:47 +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 Grosbach430052b2011-11-14 17:52:47 +00001104 assert(isRegShiftedReg() &&
1105 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1107 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001108 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001109 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001110 }
1111
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001112 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001113 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001114 assert(isRegShiftedImm() &&
1115 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001116 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001117 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001118 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001119 }
1120
Jim Grosbach580f4a92011-07-25 22:20:28 +00001121 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001123 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1124 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001125 }
1126
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001127 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001128 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001129 const SmallVectorImpl<unsigned> &RegList = getRegList();
1130 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001131 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1132 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001133 }
1134
Bill Wendling0f630752010-11-17 04:32:08 +00001135 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1136 addRegListOperands(Inst, N);
1137 }
1138
1139 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1140 addRegListOperands(Inst, N);
1141 }
1142
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001143 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
1145 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1146 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1147 }
1148
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001149 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 // Munge the lsb/width into a bitfield mask.
1152 unsigned lsb = Bitfield.LSB;
1153 unsigned width = Bitfield.Width;
1154 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1155 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1156 (32 - (lsb + width)));
1157 Inst.addOperand(MCOperand::CreateImm(Mask));
1158 }
1159
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001160 void addImmOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001164
Jim Grosbach9d390362011-10-03 23:38:36 +00001165 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1168 }
1169
Jim Grosbacha77295d2011-09-08 22:07:06 +00001170 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 // FIXME: We really want to scale the value here, but the LDRD/STRD
1173 // instruction don't encode operands that way yet.
1174 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1175 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1176 }
1177
Jim Grosbach72f39f82011-08-24 21:22:15 +00001178 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
1180 // The immediate is scaled by four in the encoding and is stored
1181 // in the MCInst as such. Lop off the low two bits here.
1182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1183 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1184 }
1185
1186 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 // The immediate is scaled by four in the encoding and is stored
1189 // in the MCInst as such. Lop off the low two bits here.
1190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1191 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1192 }
1193
Jim Grosbachf4943352011-07-25 23:09:14 +00001194 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 // The constant encodes as the immediate-1, and we store in the instruction
1197 // the bits as encoded, so subtract off one here.
1198 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1199 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1200 }
1201
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001202 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
1204 // The constant encodes as the immediate-1, and we store in the instruction
1205 // the bits as encoded, so subtract off one here.
1206 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1207 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1208 }
1209
Jim Grosbach70939ee2011-08-17 21:51:27 +00001210 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
1212 // The constant encodes as the immediate, except for 32, which encodes as
1213 // zero.
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 unsigned Imm = CE->getValue();
1216 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1217 }
1218
Jim Grosbachf6c05252011-07-21 17:23:04 +00001219 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1222 // the instruction as well.
1223 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1224 int Val = CE->getValue();
1225 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1226 }
1227
Jim Grosbach89a63372011-10-28 22:36:30 +00001228 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 // The operand is actually a t2_so_imm, but we have its bitwise
1231 // negation in the assembly source, so twiddle it here.
1232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1233 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1234 }
1235
Jim Grosbache70ec842011-10-28 22:50:54 +00001236 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 // The operand is actually a so_imm, but we have its bitwise
1239 // negation in the assembly source, so twiddle it here.
1240 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1241 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1242 }
1243
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001244 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1247 }
1248
Jim Grosbach7ce05792011-08-03 23:50:40 +00001249 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001251 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001252 }
1253
Jim Grosbach57dcb852011-10-11 17:29:55 +00001254 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 2 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1257 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1258 }
1259
Jim Grosbach7ce05792011-08-03 23:50:40 +00001260 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001262 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1263 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001264 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1265 // Special case for #-0
1266 if (Val == INT32_MIN) Val = 0;
1267 if (Val < 0) Val = -Val;
1268 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1269 } else {
1270 // For register offset, we encode the shift type and negation flag
1271 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001272 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1273 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001274 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001275 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1276 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001277 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001278 }
1279
Jim Grosbach039c2e12011-08-04 23:01:30 +00001280 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1283 assert(CE && "non-constant AM2OffsetImm operand!");
1284 int32_t Val = CE->getValue();
1285 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1286 // Special case for #-0
1287 if (Val == INT32_MIN) Val = 0;
1288 if (Val < 0) Val = -Val;
1289 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1290 Inst.addOperand(MCOperand::CreateReg(0));
1291 Inst.addOperand(MCOperand::CreateImm(Val));
1292 }
1293
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001294 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001296 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1297 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001298 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1299 // Special case for #-0
1300 if (Val == INT32_MIN) Val = 0;
1301 if (Val < 0) Val = -Val;
1302 Val = ARM_AM::getAM3Opc(AddSub, Val);
1303 } else {
1304 // For register offset, we encode the shift type and negation flag
1305 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001306 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001307 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001308 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1309 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001310 Inst.addOperand(MCOperand::CreateImm(Val));
1311 }
1312
1313 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001315 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001316 int32_t Val =
1317 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1318 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1319 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001320 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001321 }
1322
1323 // Constant offset.
1324 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1325 int32_t Val = CE->getValue();
1326 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1327 // Special case for #-0
1328 if (Val == INT32_MIN) Val = 0;
1329 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001330 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 Inst.addOperand(MCOperand::CreateReg(0));
1332 Inst.addOperand(MCOperand::CreateImm(Val));
1333 }
1334
Jim Grosbach7ce05792011-08-03 23:50:40 +00001335 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001337 // If we have an immediate that's not a constant, treat it as a label
1338 // reference needing a fixup. If it is a constant, it's something else
1339 // and we reject it.
1340 if (isImm()) {
1341 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1342 Inst.addOperand(MCOperand::CreateImm(0));
1343 return;
1344 }
1345
Jim Grosbach7ce05792011-08-03 23:50:40 +00001346 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001347 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001348 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1349 // Special case for #-0
1350 if (Val == INT32_MIN) Val = 0;
1351 if (Val < 0) Val = -Val;
1352 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001354 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001355 }
1356
Jim Grosbacha77295d2011-09-08 22:07:06 +00001357 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1358 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001359 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1360 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001361 Inst.addOperand(MCOperand::CreateImm(Val));
1362 }
1363
Jim Grosbachb6aed502011-09-09 18:37:27 +00001364 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 2 && "Invalid number of operands!");
1366 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001367 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1368 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001369 Inst.addOperand(MCOperand::CreateImm(Val));
1370 }
1371
Jim Grosbach7ce05792011-08-03 23:50:40 +00001372 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001374 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1375 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001376 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001377 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001378
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001379 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1380 addMemImm8OffsetOperands(Inst, N);
1381 }
1382
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001383 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001384 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001385 }
1386
1387 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
1389 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001390 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001391 addExpr(Inst, getImm());
1392 Inst.addOperand(MCOperand::CreateImm(0));
1393 return;
1394 }
1395
1396 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001397 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1398 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001399 Inst.addOperand(MCOperand::CreateImm(Val));
1400 }
1401
Jim Grosbach7ce05792011-08-03 23:50:40 +00001402 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001404 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001405 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001406 addExpr(Inst, getImm());
1407 Inst.addOperand(MCOperand::CreateImm(0));
1408 return;
1409 }
1410
1411 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001412 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1413 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001415 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001416
Jim Grosbach7f739be2011-09-19 22:21:13 +00001417 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001419 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1420 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001421 }
1422
1423 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1424 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001425 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1426 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001427 }
1428
Jim Grosbach7ce05792011-08-03 23:50:40 +00001429 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001431 unsigned Val =
1432 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1433 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1435 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001436 Inst.addOperand(MCOperand::CreateImm(Val));
1437 }
1438
Jim Grosbachab899c12011-09-07 23:10:15 +00001439 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1442 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1443 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001444 }
1445
Jim Grosbach7ce05792011-08-03 23:50:40 +00001446 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001448 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1449 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001450 }
1451
Jim Grosbach60f91a32011-08-19 17:55:24 +00001452 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001454 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1455 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001456 Inst.addOperand(MCOperand::CreateImm(Val));
1457 }
1458
Jim Grosbach38466302011-08-19 18:55:51 +00001459 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001461 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1462 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
1464 }
1465
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001466 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1467 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001468 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1469 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001470 Inst.addOperand(MCOperand::CreateImm(Val));
1471 }
1472
Jim Grosbachecd85892011-08-19 18:13:48 +00001473 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001475 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1476 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001477 Inst.addOperand(MCOperand::CreateImm(Val));
1478 }
1479
Jim Grosbach7ce05792011-08-03 23:50:40 +00001480 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 assert(CE && "non-constant post-idx-imm8 operand!");
1484 int Imm = CE->getValue();
1485 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001486 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001487 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1488 Inst.addOperand(MCOperand::CreateImm(Imm));
1489 }
1490
Jim Grosbach2bd01182011-10-11 21:55:36 +00001491 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1494 assert(CE && "non-constant post-idx-imm8s4 operand!");
1495 int Imm = CE->getValue();
1496 bool isAdd = Imm >= 0;
1497 if (Imm == INT32_MIN) Imm = 0;
1498 // Immediate is scaled by 4.
1499 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1500 Inst.addOperand(MCOperand::CreateImm(Imm));
1501 }
1502
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001506 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1507 }
1508
1509 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1510 assert(N == 2 && "Invalid number of operands!");
1511 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1512 // The sign, shift type, and shift amount are encoded in a single operand
1513 // using the AM2 encoding helpers.
1514 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1515 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1516 PostIdxReg.ShiftTy);
1517 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001518 }
1519
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001520 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1523 }
1524
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001525 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1528 }
1529
Jim Grosbach862019c2011-10-18 23:02:30 +00001530 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1533 }
1534
Jim Grosbach280dfad2011-10-21 18:54:25 +00001535 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 // Only the first register actually goes on the instruction. The rest
1538 // are implied by the opcode.
1539 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1540 }
1541
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001542 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // Only the first register actually goes on the instruction. The rest
1545 // are implied by the opcode.
1546 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1547 }
1548
Jim Grosbachb6310312011-10-21 20:35:01 +00001549 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
1551 // Only the first register actually goes on the instruction. The rest
1552 // are implied by the opcode.
1553 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1554 }
1555
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001556 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // Only the first register actually goes on the instruction. The rest
1559 // are implied by the opcode.
1560 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1561 }
1562
Jim Grosbach460a9052011-10-07 23:56:00 +00001563 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1566 }
1567
1568 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1571 }
1572
1573 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1576 }
1577
Jim Grosbach0e387b22011-10-17 22:26:03 +00001578 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 // The immediate encodes the type of constant as well as the value.
1581 // Mask in that this is an i8 splat.
1582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1583 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1584 }
1585
Jim Grosbachea461102011-10-17 23:09:09 +00001586 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 // The immediate encodes the type of constant as well as the value.
1589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1590 unsigned Value = CE->getValue();
1591 if (Value >= 256)
1592 Value = (Value >> 8) | 0xa00;
1593 else
1594 Value |= 0x800;
1595 Inst.addOperand(MCOperand::CreateImm(Value));
1596 }
1597
Jim Grosbach6248a542011-10-18 00:22:00 +00001598 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 // The immediate encodes the type of constant as well as the value.
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 unsigned Value = CE->getValue();
1603 if (Value >= 256 && Value <= 0xff00)
1604 Value = (Value >> 8) | 0x200;
1605 else if (Value > 0xffff && Value <= 0xff0000)
1606 Value = (Value >> 16) | 0x400;
1607 else if (Value > 0xffffff)
1608 Value = (Value >> 24) | 0x600;
1609 Inst.addOperand(MCOperand::CreateImm(Value));
1610 }
1611
1612 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 // The immediate encodes the type of constant as well as the value.
1615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1616 unsigned Value = CE->getValue();
1617 if (Value >= 256 && Value <= 0xffff)
1618 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1619 else if (Value > 0xffff && Value <= 0xffffff)
1620 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1621 else if (Value > 0xffffff)
1622 Value = (Value >> 24) | 0x600;
1623 Inst.addOperand(MCOperand::CreateImm(Value));
1624 }
1625
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001626 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 // The immediate encodes the type of constant as well as the value.
1629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1630 uint64_t Value = CE->getValue();
1631 unsigned Imm = 0;
1632 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1633 Imm |= (Value & 1) << i;
1634 }
1635 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1636 }
1637
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001638 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001639
Jim Grosbach89df9962011-08-26 21:43:41 +00001640 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001641 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001642 Op->ITMask.Mask = Mask;
1643 Op->StartLoc = S;
1644 Op->EndLoc = S;
1645 return Op;
1646 }
1647
Chris Lattner3a697562010-10-28 17:20:03 +00001648 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001649 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001650 Op->CC.Val = CC;
1651 Op->StartLoc = S;
1652 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001653 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001654 }
1655
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001656 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001657 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001658 Op->Cop.Val = CopVal;
1659 Op->StartLoc = S;
1660 Op->EndLoc = S;
1661 return Op;
1662 }
1663
1664 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001665 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001666 Op->Cop.Val = CopVal;
1667 Op->StartLoc = S;
1668 Op->EndLoc = S;
1669 return Op;
1670 }
1671
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001672 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1673 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1674 Op->Cop.Val = Val;
1675 Op->StartLoc = S;
1676 Op->EndLoc = E;
1677 return Op;
1678 }
1679
Jim Grosbachd67641b2010-12-06 18:21:12 +00001680 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001681 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001682 Op->Reg.RegNum = RegNum;
1683 Op->StartLoc = S;
1684 Op->EndLoc = S;
1685 return Op;
1686 }
1687
Chris Lattner3a697562010-10-28 17:20:03 +00001688 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001689 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001690 Op->Tok.Data = Str.data();
1691 Op->Tok.Length = Str.size();
1692 Op->StartLoc = S;
1693 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001694 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001695 }
1696
Bill Wendling50d0f582010-11-18 23:43:05 +00001697 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001698 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001699 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001700 Op->StartLoc = S;
1701 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001702 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001703 }
1704
Jim Grosbache8606dc2011-07-13 17:50:29 +00001705 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1706 unsigned SrcReg,
1707 unsigned ShiftReg,
1708 unsigned ShiftImm,
1709 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001710 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001711 Op->RegShiftedReg.ShiftTy = ShTy;
1712 Op->RegShiftedReg.SrcReg = SrcReg;
1713 Op->RegShiftedReg.ShiftReg = ShiftReg;
1714 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Owen Anderson92a20222011-07-21 18:54:16 +00001720 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1721 unsigned SrcReg,
1722 unsigned ShiftImm,
1723 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001724 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001725 Op->RegShiftedImm.ShiftTy = ShTy;
1726 Op->RegShiftedImm.SrcReg = SrcReg;
1727 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Jim Grosbach580f4a92011-07-25 22:20:28 +00001733 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001734 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001735 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001736 Op->ShifterImm.isASR = isASR;
1737 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001738 Op->StartLoc = S;
1739 Op->EndLoc = E;
1740 return Op;
1741 }
1742
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001743 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001744 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001745 Op->RotImm.Imm = Imm;
1746 Op->StartLoc = S;
1747 Op->EndLoc = E;
1748 return Op;
1749 }
1750
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001751 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1752 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001753 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001754 Op->Bitfield.LSB = LSB;
1755 Op->Bitfield.Width = Width;
1756 Op->StartLoc = S;
1757 Op->EndLoc = E;
1758 return Op;
1759 }
1760
Bill Wendling7729e062010-11-09 22:44:22 +00001761 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001762 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001763 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001765
Jim Grosbachd300b942011-09-13 22:56:44 +00001766 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001767 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001768 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001769 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001770 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001771
1772 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001773 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001774 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001775 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001776 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001777 Op->StartLoc = StartLoc;
1778 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001779 return Op;
1780 }
1781
Jim Grosbach862019c2011-10-18 23:02:30 +00001782 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1783 SMLoc S, SMLoc E) {
1784 ARMOperand *Op = new ARMOperand(k_VectorList);
1785 Op->VectorList.RegNum = RegNum;
1786 Op->VectorList.Count = Count;
1787 Op->StartLoc = S;
1788 Op->EndLoc = E;
1789 return Op;
1790 }
1791
Jim Grosbach460a9052011-10-07 23:56:00 +00001792 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1793 MCContext &Ctx) {
1794 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1795 Op->VectorIndex.Val = Idx;
1796 Op->StartLoc = S;
1797 Op->EndLoc = E;
1798 return Op;
1799 }
1800
Chris Lattner3a697562010-10-28 17:20:03 +00001801 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001802 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001803 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001804 Op->StartLoc = S;
1805 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001806 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001807 }
1808
Jim Grosbach9d390362011-10-03 23:38:36 +00001809 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001811 Op->FPImm.Val = Val;
1812 Op->StartLoc = S;
1813 Op->EndLoc = S;
1814 return Op;
1815 }
1816
Jim Grosbach7ce05792011-08-03 23:50:40 +00001817 static ARMOperand *CreateMem(unsigned BaseRegNum,
1818 const MCConstantExpr *OffsetImm,
1819 unsigned OffsetRegNum,
1820 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001821 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001822 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001823 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001824 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001825 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001826 Op->Memory.BaseRegNum = BaseRegNum;
1827 Op->Memory.OffsetImm = OffsetImm;
1828 Op->Memory.OffsetRegNum = OffsetRegNum;
1829 Op->Memory.ShiftType = ShiftType;
1830 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001831 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001832 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001833 Op->StartLoc = S;
1834 Op->EndLoc = E;
1835 return Op;
1836 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001837
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001838 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1839 ARM_AM::ShiftOpc ShiftTy,
1840 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001842 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001843 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001844 Op->PostIdxReg.isAdd = isAdd;
1845 Op->PostIdxReg.ShiftTy = ShiftTy;
1846 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001847 Op->StartLoc = S;
1848 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001849 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001850 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001851
1852 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001854 Op->MBOpt.Val = Opt;
1855 Op->StartLoc = S;
1856 Op->EndLoc = S;
1857 return Op;
1858 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001859
1860 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001861 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001862 Op->IFlags.Val = IFlags;
1863 Op->StartLoc = S;
1864 Op->EndLoc = S;
1865 return Op;
1866 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001867
1868 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001870 Op->MMask.Val = MMask;
1871 Op->StartLoc = S;
1872 Op->EndLoc = S;
1873 return Op;
1874 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001875};
1876
1877} // end anonymous namespace.
1878
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001879void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001880 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001881 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001882 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1883 << ") >";
1884 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001885 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001886 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001887 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001889 OS << "<ccout " << getReg() << ">";
1890 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001892 static const char *MaskStr[] = {
1893 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1894 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1895 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001896 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1897 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1898 break;
1899 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001900 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001901 OS << "<coprocessor number: " << getCoproc() << ">";
1902 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001903 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001904 OS << "<coprocessor register: " << getCoproc() << ">";
1905 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001906 case k_CoprocOption:
1907 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1908 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001909 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001910 OS << "<mask: " << getMSRMask() << ">";
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001913 getImm()->print(OS);
1914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001916 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1917 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001919 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001920 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001921 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001922 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001924 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1925 << PostIdxReg.RegNum;
1926 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1927 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1928 << PostIdxReg.ShiftImm;
1929 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001930 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001932 OS << "<ARM_PROC::";
1933 unsigned IFlags = getProcIFlags();
1934 for (int i=2; i >= 0; --i)
1935 if (IFlags & (1 << i))
1936 OS << ARM_PROC::IFlagsToString(1 << i);
1937 OS << ">";
1938 break;
1939 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001941 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001942 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001943 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001944 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1945 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001946 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001947 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001948 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001949 << RegShiftedReg.SrcReg
1950 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1951 << ", " << RegShiftedReg.ShiftReg << ", "
1952 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001953 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001954 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001955 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001956 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001957 << RegShiftedImm.SrcReg
1958 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1959 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001960 << ">";
1961 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001963 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1964 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001965 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001966 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1967 << ", width: " << Bitfield.Width << ">";
1968 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 case k_RegisterList:
1970 case k_DPRRegisterList:
1971 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001972 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001973
Bill Wendling5fa22a12010-11-09 23:28:44 +00001974 const SmallVectorImpl<unsigned> &RegList = getRegList();
1975 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001976 I = RegList.begin(), E = RegList.end(); I != E; ) {
1977 OS << *I;
1978 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001979 }
1980
1981 OS << ">";
1982 break;
1983 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001984 case k_VectorList:
1985 OS << "<vector_list " << VectorList.Count << " * "
1986 << VectorList.RegNum << ">";
1987 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001989 OS << "'" << getToken() << "'";
1990 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001991 case k_VectorIndex:
1992 OS << "<vectorindex " << getVectorIndex() << ">";
1993 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001994 }
1995}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001996
1997/// @name Auto-generated Match Functions
1998/// {
1999
2000static unsigned MatchRegisterName(StringRef Name);
2001
2002/// }
2003
Bob Wilson69df7232011-02-03 21:46:10 +00002004bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2005 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002006 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002007
2008 return (RegNo == (unsigned)-1);
2009}
2010
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002011/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002012/// and if it is a register name the token is eaten and the register number is
2013/// returned. Otherwise return -1.
2014///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002015int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002016 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002017 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002018
Chris Lattnere5658fa2010-10-30 04:09:10 +00002019 // FIXME: Validate register for the current architecture; we have to do
2020 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002021 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002022 unsigned RegNum = MatchRegisterName(lowerCase);
2023 if (!RegNum) {
2024 RegNum = StringSwitch<unsigned>(lowerCase)
2025 .Case("r13", ARM::SP)
2026 .Case("r14", ARM::LR)
2027 .Case("r15", ARM::PC)
2028 .Case("ip", ARM::R12)
2029 .Default(0);
2030 }
2031 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002032
Chris Lattnere5658fa2010-10-30 04:09:10 +00002033 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002034
Chris Lattnere5658fa2010-10-30 04:09:10 +00002035 return RegNum;
2036}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002037
Jim Grosbach19906722011-07-13 18:49:30 +00002038// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2039// If a recoverable error occurs, return 1. If an irrecoverable error
2040// occurs, return -1. An irrecoverable error is one where tokens have been
2041// consumed in the process of trying to parse the shifter (i.e., when it is
2042// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002043int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002044 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2045 SMLoc S = Parser.getTok().getLoc();
2046 const AsmToken &Tok = Parser.getTok();
2047 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2048
Benjamin Kramer59085362011-11-06 20:37:06 +00002049 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002050 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2051 .Case("lsl", ARM_AM::lsl)
2052 .Case("lsr", ARM_AM::lsr)
2053 .Case("asr", ARM_AM::asr)
2054 .Case("ror", ARM_AM::ror)
2055 .Case("rrx", ARM_AM::rrx)
2056 .Default(ARM_AM::no_shift);
2057
2058 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002059 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002060
Jim Grosbache8606dc2011-07-13 17:50:29 +00002061 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002062
Jim Grosbache8606dc2011-07-13 17:50:29 +00002063 // The source register for the shift has already been added to the
2064 // operand list, so we need to pop it off and combine it into the shifted
2065 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002066 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002067 if (!PrevOp->isReg())
2068 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2069 int SrcReg = PrevOp->getReg();
2070 int64_t Imm = 0;
2071 int ShiftReg = 0;
2072 if (ShiftTy == ARM_AM::rrx) {
2073 // RRX Doesn't have an explicit shift amount. The encoder expects
2074 // the shift register to be the same as the source register. Seems odd,
2075 // but OK.
2076 ShiftReg = SrcReg;
2077 } else {
2078 // Figure out if this is shifted by a constant or a register (for non-RRX).
2079 if (Parser.getTok().is(AsmToken::Hash)) {
2080 Parser.Lex(); // Eat hash.
2081 SMLoc ImmLoc = Parser.getTok().getLoc();
2082 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002083 if (getParser().ParseExpression(ShiftExpr)) {
2084 Error(ImmLoc, "invalid immediate shift value");
2085 return -1;
2086 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002087 // The expression must be evaluatable as an immediate.
2088 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002089 if (!CE) {
2090 Error(ImmLoc, "invalid immediate shift value");
2091 return -1;
2092 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002093 // Range check the immediate.
2094 // lsl, ror: 0 <= imm <= 31
2095 // lsr, asr: 0 <= imm <= 32
2096 Imm = CE->getValue();
2097 if (Imm < 0 ||
2098 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2099 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002100 Error(ImmLoc, "immediate shift value out of range");
2101 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 }
2103 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002104 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002105 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002106 if (ShiftReg == -1) {
2107 Error (L, "expected immediate or register in shift operand");
2108 return -1;
2109 }
2110 } else {
2111 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002113 return -1;
2114 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002115 }
2116
Owen Anderson92a20222011-07-21 18:54:16 +00002117 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2118 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002119 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002120 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002121 else
2122 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2123 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002124
Jim Grosbach19906722011-07-13 18:49:30 +00002125 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002126}
2127
2128
Bill Wendling50d0f582010-11-18 23:43:05 +00002129/// Try to parse a register name. The token must be an Identifier when called.
2130/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2131/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002132///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002133/// TODO this is likely to change to allow different register types and or to
2134/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002135bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002136tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002137 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002138 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002139 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002140 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002141
Bill Wendling50d0f582010-11-18 23:43:05 +00002142 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002143
Chris Lattnere5658fa2010-10-30 04:09:10 +00002144 const AsmToken &ExclaimTok = Parser.getTok();
2145 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002146 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2147 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002148 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002149 return false;
2150 }
2151
2152 // Also check for an index operand. This is only legal for vector registers,
2153 // but that'll get caught OK in operand matching, so we don't need to
2154 // explicitly filter everything else out here.
2155 if (Parser.getTok().is(AsmToken::LBrac)) {
2156 SMLoc SIdx = Parser.getTok().getLoc();
2157 Parser.Lex(); // Eat left bracket token.
2158
2159 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002160 if (getParser().ParseExpression(ImmVal))
2161 return MatchOperand_ParseFail;
2162 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2163 if (!MCE) {
2164 TokError("immediate value expected for vector index");
2165 return MatchOperand_ParseFail;
2166 }
2167
2168 SMLoc E = Parser.getTok().getLoc();
2169 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2170 Error(E, "']' expected");
2171 return MatchOperand_ParseFail;
2172 }
2173
2174 Parser.Lex(); // Eat right bracket token.
2175
2176 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2177 SIdx, E,
2178 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002179 }
2180
Bill Wendling50d0f582010-11-18 23:43:05 +00002181 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002182}
2183
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002184/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2185/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2186/// "c5", ...
2187static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002188 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2189 // but efficient.
2190 switch (Name.size()) {
2191 default: break;
2192 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002193 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002194 return -1;
2195 switch (Name[1]) {
2196 default: return -1;
2197 case '0': return 0;
2198 case '1': return 1;
2199 case '2': return 2;
2200 case '3': return 3;
2201 case '4': return 4;
2202 case '5': return 5;
2203 case '6': return 6;
2204 case '7': return 7;
2205 case '8': return 8;
2206 case '9': return 9;
2207 }
2208 break;
2209 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002210 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002211 return -1;
2212 switch (Name[2]) {
2213 default: return -1;
2214 case '0': return 10;
2215 case '1': return 11;
2216 case '2': return 12;
2217 case '3': return 13;
2218 case '4': return 14;
2219 case '5': return 15;
2220 }
2221 break;
2222 }
2223
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002224 return -1;
2225}
2226
Jim Grosbach89df9962011-08-26 21:43:41 +00002227/// parseITCondCode - Try to parse a condition code for an IT instruction.
2228ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2229parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2230 SMLoc S = Parser.getTok().getLoc();
2231 const AsmToken &Tok = Parser.getTok();
2232 if (!Tok.is(AsmToken::Identifier))
2233 return MatchOperand_NoMatch;
2234 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2235 .Case("eq", ARMCC::EQ)
2236 .Case("ne", ARMCC::NE)
2237 .Case("hs", ARMCC::HS)
2238 .Case("cs", ARMCC::HS)
2239 .Case("lo", ARMCC::LO)
2240 .Case("cc", ARMCC::LO)
2241 .Case("mi", ARMCC::MI)
2242 .Case("pl", ARMCC::PL)
2243 .Case("vs", ARMCC::VS)
2244 .Case("vc", ARMCC::VC)
2245 .Case("hi", ARMCC::HI)
2246 .Case("ls", ARMCC::LS)
2247 .Case("ge", ARMCC::GE)
2248 .Case("lt", ARMCC::LT)
2249 .Case("gt", ARMCC::GT)
2250 .Case("le", ARMCC::LE)
2251 .Case("al", ARMCC::AL)
2252 .Default(~0U);
2253 if (CC == ~0U)
2254 return MatchOperand_NoMatch;
2255 Parser.Lex(); // Eat the token.
2256
2257 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2258
2259 return MatchOperand_Success;
2260}
2261
Jim Grosbach43904292011-07-25 20:14:50 +00002262/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002263/// token must be an Identifier when called, and if it is a coprocessor
2264/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002265ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002266parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002267 SMLoc S = Parser.getTok().getLoc();
2268 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002269 if (Tok.isNot(AsmToken::Identifier))
2270 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002271
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002272 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002273 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002274 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002275
2276 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002277 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002278 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002279}
2280
Jim Grosbach43904292011-07-25 20:14:50 +00002281/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002282/// token must be an Identifier when called, and if it is a coprocessor
2283/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002284ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002285parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002286 SMLoc S = Parser.getTok().getLoc();
2287 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002288 if (Tok.isNot(AsmToken::Identifier))
2289 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002290
2291 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2292 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002293 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002294
2295 Parser.Lex(); // Eat identifier token.
2296 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002297 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002298}
2299
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002300/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2301/// coproc_option : '{' imm0_255 '}'
2302ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2303parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2304 SMLoc S = Parser.getTok().getLoc();
2305
2306 // If this isn't a '{', this isn't a coprocessor immediate operand.
2307 if (Parser.getTok().isNot(AsmToken::LCurly))
2308 return MatchOperand_NoMatch;
2309 Parser.Lex(); // Eat the '{'
2310
2311 const MCExpr *Expr;
2312 SMLoc Loc = Parser.getTok().getLoc();
2313 if (getParser().ParseExpression(Expr)) {
2314 Error(Loc, "illegal expression");
2315 return MatchOperand_ParseFail;
2316 }
2317 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2318 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2319 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2320 return MatchOperand_ParseFail;
2321 }
2322 int Val = CE->getValue();
2323
2324 // Check for and consume the closing '}'
2325 if (Parser.getTok().isNot(AsmToken::RCurly))
2326 return MatchOperand_ParseFail;
2327 SMLoc E = Parser.getTok().getLoc();
2328 Parser.Lex(); // Eat the '}'
2329
2330 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2331 return MatchOperand_Success;
2332}
2333
Jim Grosbachd0588e22011-09-14 18:08:35 +00002334// For register list parsing, we need to map from raw GPR register numbering
2335// to the enumeration values. The enumeration values aren't sorted by
2336// register number due to our using "sp", "lr" and "pc" as canonical names.
2337static unsigned getNextRegister(unsigned Reg) {
2338 // If this is a GPR, we need to do it manually, otherwise we can rely
2339 // on the sort ordering of the enumeration since the other reg-classes
2340 // are sane.
2341 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2342 return Reg + 1;
2343 switch(Reg) {
2344 default: assert(0 && "Invalid GPR number!");
2345 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2346 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2347 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2348 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2349 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2350 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2351 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2352 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2353 }
2354}
2355
Jim Grosbachce485e72011-11-11 21:27:40 +00002356// Return the low-subreg of a given Q register.
2357static unsigned getDRegFromQReg(unsigned QReg) {
2358 switch (QReg) {
2359 default: llvm_unreachable("expected a Q register!");
2360 case ARM::Q0: return ARM::D0;
2361 case ARM::Q1: return ARM::D2;
2362 case ARM::Q2: return ARM::D4;
2363 case ARM::Q3: return ARM::D6;
2364 case ARM::Q4: return ARM::D8;
2365 case ARM::Q5: return ARM::D10;
2366 case ARM::Q6: return ARM::D12;
2367 case ARM::Q7: return ARM::D14;
2368 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002369 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002370 case ARM::Q10: return ARM::D20;
2371 case ARM::Q11: return ARM::D22;
2372 case ARM::Q12: return ARM::D24;
2373 case ARM::Q13: return ARM::D26;
2374 case ARM::Q14: return ARM::D28;
2375 case ARM::Q15: return ARM::D30;
2376 }
2377}
2378
Jim Grosbachd0588e22011-09-14 18:08:35 +00002379/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002380bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002381parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002382 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002383 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002384 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002385 Parser.Lex(); // Eat '{' token.
2386 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002387
Jim Grosbachd0588e22011-09-14 18:08:35 +00002388 // Check the first register in the list to see what register class
2389 // this is a list of.
2390 int Reg = tryParseRegister();
2391 if (Reg == -1)
2392 return Error(RegLoc, "register expected");
2393
Jim Grosbachce485e72011-11-11 21:27:40 +00002394 // The reglist instructions have at most 16 registers, so reserve
2395 // space for that many.
2396 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2397
2398 // Allow Q regs and just interpret them as the two D sub-registers.
2399 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2400 Reg = getDRegFromQReg(Reg);
2401 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2402 ++Reg;
2403 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002404 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002405 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2407 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2408 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2409 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2410 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2411 else
2412 return Error(RegLoc, "invalid register in register list");
2413
Jim Grosbachce485e72011-11-11 21:27:40 +00002414 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002415 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002416
Jim Grosbachd0588e22011-09-14 18:08:35 +00002417 // This starts immediately after the first register token in the list,
2418 // so we can see either a comma or a minus (range separator) as a legal
2419 // next token.
2420 while (Parser.getTok().is(AsmToken::Comma) ||
2421 Parser.getTok().is(AsmToken::Minus)) {
2422 if (Parser.getTok().is(AsmToken::Minus)) {
2423 Parser.Lex(); // Eat the comma.
2424 SMLoc EndLoc = Parser.getTok().getLoc();
2425 int EndReg = tryParseRegister();
2426 if (EndReg == -1)
2427 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002428 // Allow Q regs and just interpret them as the two D sub-registers.
2429 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2430 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002431 // If the register is the same as the start reg, there's nothing
2432 // more to do.
2433 if (Reg == EndReg)
2434 continue;
2435 // The register must be in the same register class as the first.
2436 if (!RC->contains(EndReg))
2437 return Error(EndLoc, "invalid register in register list");
2438 // Ranges must go from low to high.
2439 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2440 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002441
Jim Grosbachd0588e22011-09-14 18:08:35 +00002442 // Add all the registers in the range to the register list.
2443 while (Reg != EndReg) {
2444 Reg = getNextRegister(Reg);
2445 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2446 }
2447 continue;
2448 }
2449 Parser.Lex(); // Eat the comma.
2450 RegLoc = Parser.getTok().getLoc();
2451 int OldReg = Reg;
2452 Reg = tryParseRegister();
2453 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002454 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002455 // Allow Q regs and just interpret them as the two D sub-registers.
2456 bool isQReg = false;
2457 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2458 Reg = getDRegFromQReg(Reg);
2459 isQReg = true;
2460 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002461 // The register must be in the same register class as the first.
2462 if (!RC->contains(Reg))
2463 return Error(RegLoc, "invalid register in register list");
2464 // List must be monotonically increasing.
2465 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2466 return Error(RegLoc, "register list not in ascending order");
2467 // VFP register lists must also be contiguous.
2468 // It's OK to use the enumeration values directly here rather, as the
2469 // VFP register classes have the enum sorted properly.
2470 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2471 Reg != OldReg + 1)
2472 return Error(RegLoc, "non-contiguous register range");
2473 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002474 if (isQReg)
2475 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002476 }
2477
Jim Grosbachd0588e22011-09-14 18:08:35 +00002478 SMLoc E = Parser.getTok().getLoc();
2479 if (Parser.getTok().isNot(AsmToken::RCurly))
2480 return Error(E, "'}' expected");
2481 Parser.Lex(); // Eat '}' token.
2482
Bill Wendling50d0f582010-11-18 23:43:05 +00002483 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2484 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002485}
2486
Jim Grosbach862019c2011-10-18 23:02:30 +00002487// parse a vector register list
2488ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2489parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach5c984e42011-11-15 21:45:55 +00002490 SMLoc S = Parser.getTok().getLoc();
2491 // As an extension (to match gas), support a plain D register or Q register
2492 // (without encosing curly braces) as a single or double entry list,
2493 // respectively.
2494 if (Parser.getTok().is(AsmToken::Identifier)) {
2495 int Reg = tryParseRegister();
2496 if (Reg == -1)
2497 return MatchOperand_NoMatch;
2498 SMLoc E = Parser.getTok().getLoc();
2499 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
2500 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2501 return MatchOperand_Success;
2502 }
2503 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2504 Reg = getDRegFromQReg(Reg);
2505 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2506 return MatchOperand_Success;
2507 }
2508 Error(S, "vector register expected");
2509 return MatchOperand_ParseFail;
2510 }
2511
2512 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002513 return MatchOperand_NoMatch;
2514
Jim Grosbach862019c2011-10-18 23:02:30 +00002515 Parser.Lex(); // Eat '{' token.
2516 SMLoc RegLoc = Parser.getTok().getLoc();
2517
2518 int Reg = tryParseRegister();
2519 if (Reg == -1) {
2520 Error(RegLoc, "register expected");
2521 return MatchOperand_ParseFail;
2522 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002523 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002524 unsigned FirstReg = Reg;
2525 // The list is of D registers, but we also allow Q regs and just interpret
2526 // them as the two D sub-registers.
2527 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2528 FirstReg = Reg = getDRegFromQReg(Reg);
2529 ++Reg;
2530 ++Count;
2531 }
2532
Jim Grosbach862019c2011-10-18 23:02:30 +00002533 while (Parser.getTok().is(AsmToken::Comma)) {
2534 Parser.Lex(); // Eat the comma.
2535 RegLoc = Parser.getTok().getLoc();
2536 int OldReg = Reg;
2537 Reg = tryParseRegister();
2538 if (Reg == -1) {
2539 Error(RegLoc, "register expected");
2540 return MatchOperand_ParseFail;
2541 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002542 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002543 // It's OK to use the enumeration values directly here rather, as the
2544 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002545 //
2546 // The list is of D registers, but we also allow Q regs and just interpret
2547 // them as the two D sub-registers.
2548 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2549 Reg = getDRegFromQReg(Reg);
2550 if (Reg != OldReg + 1) {
2551 Error(RegLoc, "non-contiguous register range");
2552 return MatchOperand_ParseFail;
2553 }
2554 ++Reg;
2555 Count += 2;
2556 continue;
2557 }
2558 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002559 if (Reg != OldReg + 1) {
2560 Error(RegLoc, "non-contiguous register range");
2561 return MatchOperand_ParseFail;
2562 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002563 ++Count;
2564 }
2565
2566 SMLoc E = Parser.getTok().getLoc();
2567 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2568 Error(E, "'}' expected");
2569 return MatchOperand_ParseFail;
2570 }
2571 Parser.Lex(); // Eat '}' token.
2572
2573 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2574 return MatchOperand_Success;
2575}
2576
Jim Grosbach43904292011-07-25 20:14:50 +00002577/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002578ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002579parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002580 SMLoc S = Parser.getTok().getLoc();
2581 const AsmToken &Tok = Parser.getTok();
2582 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2583 StringRef OptStr = Tok.getString();
2584
2585 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2586 .Case("sy", ARM_MB::SY)
2587 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002588 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002589 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002590 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002591 .Case("ishst", ARM_MB::ISHST)
2592 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002593 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002594 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002595 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002596 .Case("osh", ARM_MB::OSH)
2597 .Case("oshst", ARM_MB::OSHST)
2598 .Default(~0U);
2599
2600 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002601 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002602
2603 Parser.Lex(); // Eat identifier token.
2604 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002605 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002606}
2607
Jim Grosbach43904292011-07-25 20:14:50 +00002608/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002609ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002610parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002611 SMLoc S = Parser.getTok().getLoc();
2612 const AsmToken &Tok = Parser.getTok();
2613 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2614 StringRef IFlagsStr = Tok.getString();
2615
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002616 // An iflags string of "none" is interpreted to mean that none of the AIF
2617 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002618 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002619 if (IFlagsStr != "none") {
2620 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2621 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2622 .Case("a", ARM_PROC::A)
2623 .Case("i", ARM_PROC::I)
2624 .Case("f", ARM_PROC::F)
2625 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002626
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002627 // If some specific iflag is already set, it means that some letter is
2628 // present more than once, this is not acceptable.
2629 if (Flag == ~0U || (IFlags & Flag))
2630 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002631
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002632 IFlags |= Flag;
2633 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002634 }
2635
2636 Parser.Lex(); // Eat identifier token.
2637 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2638 return MatchOperand_Success;
2639}
2640
Jim Grosbach43904292011-07-25 20:14:50 +00002641/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002642ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002643parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002644 SMLoc S = Parser.getTok().getLoc();
2645 const AsmToken &Tok = Parser.getTok();
2646 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2647 StringRef Mask = Tok.getString();
2648
James Molloyacad68d2011-09-28 14:21:38 +00002649 if (isMClass()) {
2650 // See ARMv6-M 10.1.1
2651 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2652 .Case("apsr", 0)
2653 .Case("iapsr", 1)
2654 .Case("eapsr", 2)
2655 .Case("xpsr", 3)
2656 .Case("ipsr", 5)
2657 .Case("epsr", 6)
2658 .Case("iepsr", 7)
2659 .Case("msp", 8)
2660 .Case("psp", 9)
2661 .Case("primask", 16)
2662 .Case("basepri", 17)
2663 .Case("basepri_max", 18)
2664 .Case("faultmask", 19)
2665 .Case("control", 20)
2666 .Default(~0U);
2667
2668 if (FlagsVal == ~0U)
2669 return MatchOperand_NoMatch;
2670
2671 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2672 // basepri, basepri_max and faultmask only valid for V7m.
2673 return MatchOperand_NoMatch;
2674
2675 Parser.Lex(); // Eat identifier token.
2676 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2677 return MatchOperand_Success;
2678 }
2679
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002680 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2681 size_t Start = 0, Next = Mask.find('_');
2682 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002683 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002684 if (Next != StringRef::npos)
2685 Flags = Mask.slice(Next+1, Mask.size());
2686
2687 // FlagsVal contains the complete mask:
2688 // 3-0: Mask
2689 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2690 unsigned FlagsVal = 0;
2691
2692 if (SpecReg == "apsr") {
2693 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002694 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002695 .Case("g", 0x4) // same as CPSR_s
2696 .Case("nzcvqg", 0xc) // same as CPSR_fs
2697 .Default(~0U);
2698
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002699 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002700 if (!Flags.empty())
2701 return MatchOperand_NoMatch;
2702 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002703 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002704 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002705 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002706 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2707 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002708 for (int i = 0, e = Flags.size(); i != e; ++i) {
2709 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2710 .Case("c", 1)
2711 .Case("x", 2)
2712 .Case("s", 4)
2713 .Case("f", 8)
2714 .Default(~0U);
2715
2716 // If some specific flag is already set, it means that some letter is
2717 // present more than once, this is not acceptable.
2718 if (FlagsVal == ~0U || (FlagsVal & Flag))
2719 return MatchOperand_NoMatch;
2720 FlagsVal |= Flag;
2721 }
2722 } else // No match for special register.
2723 return MatchOperand_NoMatch;
2724
Owen Anderson7784f1d2011-10-21 18:43:28 +00002725 // Special register without flags is NOT equivalent to "fc" flags.
2726 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2727 // two lines would enable gas compatibility at the expense of breaking
2728 // round-tripping.
2729 //
2730 // if (!FlagsVal)
2731 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002732
2733 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2734 if (SpecReg == "spsr")
2735 FlagsVal |= 16;
2736
2737 Parser.Lex(); // Eat identifier token.
2738 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2739 return MatchOperand_Success;
2740}
2741
Jim Grosbachf6c05252011-07-21 17:23:04 +00002742ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2743parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2744 int Low, int High) {
2745 const AsmToken &Tok = Parser.getTok();
2746 if (Tok.isNot(AsmToken::Identifier)) {
2747 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2748 return MatchOperand_ParseFail;
2749 }
2750 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002751 std::string LowerOp = Op.lower();
2752 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002753 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2754 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2755 return MatchOperand_ParseFail;
2756 }
2757 Parser.Lex(); // Eat shift type token.
2758
2759 // There must be a '#' and a shift amount.
2760 if (Parser.getTok().isNot(AsmToken::Hash)) {
2761 Error(Parser.getTok().getLoc(), "'#' expected");
2762 return MatchOperand_ParseFail;
2763 }
2764 Parser.Lex(); // Eat hash token.
2765
2766 const MCExpr *ShiftAmount;
2767 SMLoc Loc = Parser.getTok().getLoc();
2768 if (getParser().ParseExpression(ShiftAmount)) {
2769 Error(Loc, "illegal expression");
2770 return MatchOperand_ParseFail;
2771 }
2772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2773 if (!CE) {
2774 Error(Loc, "constant expression expected");
2775 return MatchOperand_ParseFail;
2776 }
2777 int Val = CE->getValue();
2778 if (Val < Low || Val > High) {
2779 Error(Loc, "immediate value out of range");
2780 return MatchOperand_ParseFail;
2781 }
2782
2783 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2784
2785 return MatchOperand_Success;
2786}
2787
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002788ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2789parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2790 const AsmToken &Tok = Parser.getTok();
2791 SMLoc S = Tok.getLoc();
2792 if (Tok.isNot(AsmToken::Identifier)) {
2793 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2794 return MatchOperand_ParseFail;
2795 }
2796 int Val = StringSwitch<int>(Tok.getString())
2797 .Case("be", 1)
2798 .Case("le", 0)
2799 .Default(-1);
2800 Parser.Lex(); // Eat the token.
2801
2802 if (Val == -1) {
2803 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2804 return MatchOperand_ParseFail;
2805 }
2806 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2807 getContext()),
2808 S, Parser.getTok().getLoc()));
2809 return MatchOperand_Success;
2810}
2811
Jim Grosbach580f4a92011-07-25 22:20:28 +00002812/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2813/// instructions. Legal values are:
2814/// lsl #n 'n' in [0,31]
2815/// asr #n 'n' in [1,32]
2816/// n == 32 encoded as n == 0.
2817ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2818parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2819 const AsmToken &Tok = Parser.getTok();
2820 SMLoc S = Tok.getLoc();
2821 if (Tok.isNot(AsmToken::Identifier)) {
2822 Error(S, "shift operator 'asr' or 'lsl' expected");
2823 return MatchOperand_ParseFail;
2824 }
2825 StringRef ShiftName = Tok.getString();
2826 bool isASR;
2827 if (ShiftName == "lsl" || ShiftName == "LSL")
2828 isASR = false;
2829 else if (ShiftName == "asr" || ShiftName == "ASR")
2830 isASR = true;
2831 else {
2832 Error(S, "shift operator 'asr' or 'lsl' expected");
2833 return MatchOperand_ParseFail;
2834 }
2835 Parser.Lex(); // Eat the operator.
2836
2837 // A '#' and a shift amount.
2838 if (Parser.getTok().isNot(AsmToken::Hash)) {
2839 Error(Parser.getTok().getLoc(), "'#' expected");
2840 return MatchOperand_ParseFail;
2841 }
2842 Parser.Lex(); // Eat hash token.
2843
2844 const MCExpr *ShiftAmount;
2845 SMLoc E = Parser.getTok().getLoc();
2846 if (getParser().ParseExpression(ShiftAmount)) {
2847 Error(E, "malformed shift expression");
2848 return MatchOperand_ParseFail;
2849 }
2850 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2851 if (!CE) {
2852 Error(E, "shift amount must be an immediate");
2853 return MatchOperand_ParseFail;
2854 }
2855
2856 int64_t Val = CE->getValue();
2857 if (isASR) {
2858 // Shift amount must be in [1,32]
2859 if (Val < 1 || Val > 32) {
2860 Error(E, "'asr' shift amount must be in range [1,32]");
2861 return MatchOperand_ParseFail;
2862 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002863 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2864 if (isThumb() && Val == 32) {
2865 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2866 return MatchOperand_ParseFail;
2867 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002868 if (Val == 32) Val = 0;
2869 } else {
2870 // Shift amount must be in [1,32]
2871 if (Val < 0 || Val > 31) {
2872 Error(E, "'lsr' shift amount must be in range [0,31]");
2873 return MatchOperand_ParseFail;
2874 }
2875 }
2876
2877 E = Parser.getTok().getLoc();
2878 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2879
2880 return MatchOperand_Success;
2881}
2882
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002883/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2884/// of instructions. Legal values are:
2885/// ror #n 'n' in {0, 8, 16, 24}
2886ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2887parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2888 const AsmToken &Tok = Parser.getTok();
2889 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002890 if (Tok.isNot(AsmToken::Identifier))
2891 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002892 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002893 if (ShiftName != "ror" && ShiftName != "ROR")
2894 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002895 Parser.Lex(); // Eat the operator.
2896
2897 // A '#' and a rotate amount.
2898 if (Parser.getTok().isNot(AsmToken::Hash)) {
2899 Error(Parser.getTok().getLoc(), "'#' expected");
2900 return MatchOperand_ParseFail;
2901 }
2902 Parser.Lex(); // Eat hash token.
2903
2904 const MCExpr *ShiftAmount;
2905 SMLoc E = Parser.getTok().getLoc();
2906 if (getParser().ParseExpression(ShiftAmount)) {
2907 Error(E, "malformed rotate expression");
2908 return MatchOperand_ParseFail;
2909 }
2910 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2911 if (!CE) {
2912 Error(E, "rotate amount must be an immediate");
2913 return MatchOperand_ParseFail;
2914 }
2915
2916 int64_t Val = CE->getValue();
2917 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2918 // normally, zero is represented in asm by omitting the rotate operand
2919 // entirely.
2920 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2921 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2922 return MatchOperand_ParseFail;
2923 }
2924
2925 E = Parser.getTok().getLoc();
2926 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2927
2928 return MatchOperand_Success;
2929}
2930
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002931ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2932parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2933 SMLoc S = Parser.getTok().getLoc();
2934 // The bitfield descriptor is really two operands, the LSB and the width.
2935 if (Parser.getTok().isNot(AsmToken::Hash)) {
2936 Error(Parser.getTok().getLoc(), "'#' expected");
2937 return MatchOperand_ParseFail;
2938 }
2939 Parser.Lex(); // Eat hash token.
2940
2941 const MCExpr *LSBExpr;
2942 SMLoc E = Parser.getTok().getLoc();
2943 if (getParser().ParseExpression(LSBExpr)) {
2944 Error(E, "malformed immediate expression");
2945 return MatchOperand_ParseFail;
2946 }
2947 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2948 if (!CE) {
2949 Error(E, "'lsb' operand must be an immediate");
2950 return MatchOperand_ParseFail;
2951 }
2952
2953 int64_t LSB = CE->getValue();
2954 // The LSB must be in the range [0,31]
2955 if (LSB < 0 || LSB > 31) {
2956 Error(E, "'lsb' operand must be in the range [0,31]");
2957 return MatchOperand_ParseFail;
2958 }
2959 E = Parser.getTok().getLoc();
2960
2961 // Expect another immediate operand.
2962 if (Parser.getTok().isNot(AsmToken::Comma)) {
2963 Error(Parser.getTok().getLoc(), "too few operands");
2964 return MatchOperand_ParseFail;
2965 }
2966 Parser.Lex(); // Eat hash token.
2967 if (Parser.getTok().isNot(AsmToken::Hash)) {
2968 Error(Parser.getTok().getLoc(), "'#' expected");
2969 return MatchOperand_ParseFail;
2970 }
2971 Parser.Lex(); // Eat hash token.
2972
2973 const MCExpr *WidthExpr;
2974 if (getParser().ParseExpression(WidthExpr)) {
2975 Error(E, "malformed immediate expression");
2976 return MatchOperand_ParseFail;
2977 }
2978 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2979 if (!CE) {
2980 Error(E, "'width' operand must be an immediate");
2981 return MatchOperand_ParseFail;
2982 }
2983
2984 int64_t Width = CE->getValue();
2985 // The LSB must be in the range [1,32-lsb]
2986 if (Width < 1 || Width > 32 - LSB) {
2987 Error(E, "'width' operand must be in the range [1,32-lsb]");
2988 return MatchOperand_ParseFail;
2989 }
2990 E = Parser.getTok().getLoc();
2991
2992 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2993
2994 return MatchOperand_Success;
2995}
2996
Jim Grosbach7ce05792011-08-03 23:50:40 +00002997ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2998parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2999 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003000 // postidx_reg := '+' register {, shift}
3001 // | '-' register {, shift}
3002 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003003
3004 // This method must return MatchOperand_NoMatch without consuming any tokens
3005 // in the case where there is no match, as other alternatives take other
3006 // parse methods.
3007 AsmToken Tok = Parser.getTok();
3008 SMLoc S = Tok.getLoc();
3009 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003010 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003011 int Reg = -1;
3012 if (Tok.is(AsmToken::Plus)) {
3013 Parser.Lex(); // Eat the '+' token.
3014 haveEaten = true;
3015 } else if (Tok.is(AsmToken::Minus)) {
3016 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003017 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003018 haveEaten = true;
3019 }
3020 if (Parser.getTok().is(AsmToken::Identifier))
3021 Reg = tryParseRegister();
3022 if (Reg == -1) {
3023 if (!haveEaten)
3024 return MatchOperand_NoMatch;
3025 Error(Parser.getTok().getLoc(), "register expected");
3026 return MatchOperand_ParseFail;
3027 }
3028 SMLoc E = Parser.getTok().getLoc();
3029
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003030 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3031 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003032 if (Parser.getTok().is(AsmToken::Comma)) {
3033 Parser.Lex(); // Eat the ','.
3034 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3035 return MatchOperand_ParseFail;
3036 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003037
3038 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3039 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003040
3041 return MatchOperand_Success;
3042}
3043
Jim Grosbach251bf252011-08-10 21:56:18 +00003044ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3045parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3046 // Check for a post-index addressing register operand. Specifically:
3047 // am3offset := '+' register
3048 // | '-' register
3049 // | register
3050 // | # imm
3051 // | # + imm
3052 // | # - imm
3053
3054 // This method must return MatchOperand_NoMatch without consuming any tokens
3055 // in the case where there is no match, as other alternatives take other
3056 // parse methods.
3057 AsmToken Tok = Parser.getTok();
3058 SMLoc S = Tok.getLoc();
3059
3060 // Do immediates first, as we always parse those if we have a '#'.
3061 if (Parser.getTok().is(AsmToken::Hash)) {
3062 Parser.Lex(); // Eat the '#'.
3063 // Explicitly look for a '-', as we need to encode negative zero
3064 // differently.
3065 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3066 const MCExpr *Offset;
3067 if (getParser().ParseExpression(Offset))
3068 return MatchOperand_ParseFail;
3069 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3070 if (!CE) {
3071 Error(S, "constant expression expected");
3072 return MatchOperand_ParseFail;
3073 }
3074 SMLoc E = Tok.getLoc();
3075 // Negative zero is encoded as the flag value INT32_MIN.
3076 int32_t Val = CE->getValue();
3077 if (isNegative && Val == 0)
3078 Val = INT32_MIN;
3079
3080 Operands.push_back(
3081 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3082
3083 return MatchOperand_Success;
3084 }
3085
3086
3087 bool haveEaten = false;
3088 bool isAdd = true;
3089 int Reg = -1;
3090 if (Tok.is(AsmToken::Plus)) {
3091 Parser.Lex(); // Eat the '+' token.
3092 haveEaten = true;
3093 } else if (Tok.is(AsmToken::Minus)) {
3094 Parser.Lex(); // Eat the '-' token.
3095 isAdd = false;
3096 haveEaten = true;
3097 }
3098 if (Parser.getTok().is(AsmToken::Identifier))
3099 Reg = tryParseRegister();
3100 if (Reg == -1) {
3101 if (!haveEaten)
3102 return MatchOperand_NoMatch;
3103 Error(Parser.getTok().getLoc(), "register expected");
3104 return MatchOperand_ParseFail;
3105 }
3106 SMLoc E = Parser.getTok().getLoc();
3107
3108 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3109 0, S, E));
3110
3111 return MatchOperand_Success;
3112}
3113
Jim Grosbacha77295d2011-09-08 22:07:06 +00003114/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3115/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3116/// when they refer multiple MIOperands inside a single one.
3117bool ARMAsmParser::
3118cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3119 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3120 // Rt, Rt2
3121 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3122 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3123 // Create a writeback register dummy placeholder.
3124 Inst.addOperand(MCOperand::CreateReg(0));
3125 // addr
3126 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3127 // pred
3128 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3129 return true;
3130}
3131
3132/// cvtT2StrdPre - Convert parsed operands to MCInst.
3133/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3134/// when they refer multiple MIOperands inside a single one.
3135bool ARMAsmParser::
3136cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3137 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3138 // Create a writeback register dummy placeholder.
3139 Inst.addOperand(MCOperand::CreateReg(0));
3140 // Rt, Rt2
3141 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3142 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3143 // addr
3144 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3145 // pred
3146 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3147 return true;
3148}
3149
Jim Grosbacheeec0252011-09-08 00:39:19 +00003150/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3151/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3152/// when they refer multiple MIOperands inside a single one.
3153bool ARMAsmParser::
3154cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3155 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3156 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3157
3158 // Create a writeback register dummy placeholder.
3159 Inst.addOperand(MCOperand::CreateImm(0));
3160
3161 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3162 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3163 return true;
3164}
3165
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003166/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3167/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3168/// when they refer multiple MIOperands inside a single one.
3169bool ARMAsmParser::
3170cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3171 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3172 // Create a writeback register dummy placeholder.
3173 Inst.addOperand(MCOperand::CreateImm(0));
3174 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3175 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3176 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3177 return true;
3178}
3179
Jim Grosbach1355cf12011-07-26 17:10:22 +00003180/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003181/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3182/// when they refer multiple MIOperands inside a single one.
3183bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003184cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003185 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3186 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3187
3188 // Create a writeback register dummy placeholder.
3189 Inst.addOperand(MCOperand::CreateImm(0));
3190
Jim Grosbach7ce05792011-08-03 23:50:40 +00003191 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003192 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3193 return true;
3194}
3195
Owen Anderson9ab0f252011-08-26 20:43:14 +00003196/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3197/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3198/// when they refer multiple MIOperands inside a single one.
3199bool ARMAsmParser::
3200cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3201 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3202 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3203
3204 // Create a writeback register dummy placeholder.
3205 Inst.addOperand(MCOperand::CreateImm(0));
3206
3207 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3208 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3209 return true;
3210}
3211
3212
Jim Grosbach548340c2011-08-11 19:22:40 +00003213/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3214/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3215/// when they refer multiple MIOperands inside a single one.
3216bool ARMAsmParser::
3217cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3218 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3219 // Create a writeback register dummy placeholder.
3220 Inst.addOperand(MCOperand::CreateImm(0));
3221 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3222 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3223 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3224 return true;
3225}
3226
Jim Grosbach1355cf12011-07-26 17:10:22 +00003227/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003228/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3229/// when they refer multiple MIOperands inside a single one.
3230bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003231cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003232 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3233 // Create a writeback register dummy placeholder.
3234 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003235 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3236 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3237 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003238 return true;
3239}
3240
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003241/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3242/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3243/// when they refer multiple MIOperands inside a single one.
3244bool ARMAsmParser::
3245cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3246 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3247 // Create a writeback register dummy placeholder.
3248 Inst.addOperand(MCOperand::CreateImm(0));
3249 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3250 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3251 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3252 return true;
3253}
3254
Jim Grosbach7ce05792011-08-03 23:50:40 +00003255/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3256/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3257/// when they refer multiple MIOperands inside a single one.
3258bool ARMAsmParser::
3259cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3260 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3261 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003262 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003263 // Create a writeback register dummy placeholder.
3264 Inst.addOperand(MCOperand::CreateImm(0));
3265 // addr
3266 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3267 // offset
3268 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3269 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003270 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3271 return true;
3272}
3273
Jim Grosbach7ce05792011-08-03 23:50:40 +00003274/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003275/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3276/// when they refer multiple MIOperands inside a single one.
3277bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003278cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3279 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3280 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003281 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003282 // Create a writeback register dummy placeholder.
3283 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003284 // addr
3285 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3286 // offset
3287 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3288 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003289 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3290 return true;
3291}
3292
Jim Grosbach7ce05792011-08-03 23:50:40 +00003293/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003294/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3295/// when they refer multiple MIOperands inside a single one.
3296bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003297cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3298 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003299 // Create a writeback register dummy placeholder.
3300 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003301 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003302 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003303 // addr
3304 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3305 // offset
3306 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3307 // pred
3308 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3309 return true;
3310}
3311
3312/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3313/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3314/// when they refer multiple MIOperands inside a single one.
3315bool ARMAsmParser::
3316cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3317 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3318 // Create a writeback register dummy placeholder.
3319 Inst.addOperand(MCOperand::CreateImm(0));
3320 // Rt
3321 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3322 // addr
3323 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3324 // offset
3325 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3326 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003327 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3328 return true;
3329}
3330
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003331/// cvtLdrdPre - Convert parsed operands to MCInst.
3332/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3333/// when they refer multiple MIOperands inside a single one.
3334bool ARMAsmParser::
3335cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3336 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3337 // Rt, Rt2
3338 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3339 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3340 // Create a writeback register dummy placeholder.
3341 Inst.addOperand(MCOperand::CreateImm(0));
3342 // addr
3343 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3344 // pred
3345 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3346 return true;
3347}
3348
Jim Grosbach14605d12011-08-11 20:28:23 +00003349/// cvtStrdPre - Convert parsed operands to MCInst.
3350/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3351/// when they refer multiple MIOperands inside a single one.
3352bool ARMAsmParser::
3353cvtStrdPre(MCInst &Inst, unsigned Opcode,
3354 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3355 // Create a writeback register dummy placeholder.
3356 Inst.addOperand(MCOperand::CreateImm(0));
3357 // Rt, Rt2
3358 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3359 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3360 // addr
3361 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3362 // pred
3363 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3364 return true;
3365}
3366
Jim Grosbach623a4542011-08-10 22:42:16 +00003367/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3368/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3369/// when they refer multiple MIOperands inside a single one.
3370bool ARMAsmParser::
3371cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3372 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3374 // Create a writeback register dummy placeholder.
3375 Inst.addOperand(MCOperand::CreateImm(0));
3376 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3377 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3378 return true;
3379}
3380
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003381/// cvtThumbMultiple- Convert parsed operands to MCInst.
3382/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3383/// when they refer multiple MIOperands inside a single one.
3384bool ARMAsmParser::
3385cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3386 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3387 // The second source operand must be the same register as the destination
3388 // operand.
3389 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003390 (((ARMOperand*)Operands[3])->getReg() !=
3391 ((ARMOperand*)Operands[5])->getReg()) &&
3392 (((ARMOperand*)Operands[3])->getReg() !=
3393 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003394 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003395 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003396 return false;
3397 }
3398 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3399 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003400 // If we have a three-operand form, make sure to set Rn to be the operand
3401 // that isn't the same as Rd.
3402 unsigned RegOp = 4;
3403 if (Operands.size() == 6 &&
3404 ((ARMOperand*)Operands[4])->getReg() ==
3405 ((ARMOperand*)Operands[3])->getReg())
3406 RegOp = 5;
3407 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3408 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003409 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3410
3411 return true;
3412}
Jim Grosbach623a4542011-08-10 22:42:16 +00003413
Jim Grosbach12431322011-10-24 22:16:58 +00003414bool ARMAsmParser::
3415cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3416 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3417 // Vd
3418 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3419 // Create a writeback register dummy placeholder.
3420 Inst.addOperand(MCOperand::CreateImm(0));
3421 // Vn
3422 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3423 // pred
3424 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3425 return true;
3426}
3427
3428bool ARMAsmParser::
3429cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3430 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3431 // Vd
3432 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3433 // Create a writeback register dummy placeholder.
3434 Inst.addOperand(MCOperand::CreateImm(0));
3435 // Vn
3436 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3437 // Vm
3438 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3439 // pred
3440 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3441 return true;
3442}
3443
Jim Grosbach4334e032011-10-31 21:50:31 +00003444bool ARMAsmParser::
3445cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3446 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3447 // Create a writeback register dummy placeholder.
3448 Inst.addOperand(MCOperand::CreateImm(0));
3449 // Vn
3450 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3451 // Vt
3452 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3453 // pred
3454 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3455 return true;
3456}
3457
3458bool ARMAsmParser::
3459cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3460 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3461 // Create a writeback register dummy placeholder.
3462 Inst.addOperand(MCOperand::CreateImm(0));
3463 // Vn
3464 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3465 // Vm
3466 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3467 // Vt
3468 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3469 // pred
3470 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3471 return true;
3472}
3473
Bill Wendlinge7176102010-11-06 22:36:58 +00003474/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003475/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003476bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003477parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003478 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003479 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003480 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003481 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003482 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003483
Sean Callanan18b83232010-01-19 21:44:56 +00003484 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003485 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003486 if (BaseRegNum == -1)
3487 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003488
Daniel Dunbar05710932011-01-18 05:34:17 +00003489 // The next token must either be a comma or a closing bracket.
3490 const AsmToken &Tok = Parser.getTok();
3491 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003492 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003493
Jim Grosbach7ce05792011-08-03 23:50:40 +00003494 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003495 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003496 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003497
Jim Grosbach7ce05792011-08-03 23:50:40 +00003498 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003499 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003500
Jim Grosbachfb12f352011-09-19 18:42:21 +00003501 // If there's a pre-indexing writeback marker, '!', just add it as a token
3502 // operand. It's rather odd, but syntactically valid.
3503 if (Parser.getTok().is(AsmToken::Exclaim)) {
3504 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3505 Parser.Lex(); // Eat the '!'.
3506 }
3507
Jim Grosbach7ce05792011-08-03 23:50:40 +00003508 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003509 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003510
Jim Grosbach7ce05792011-08-03 23:50:40 +00003511 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3512 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003513
Jim Grosbach57dcb852011-10-11 17:29:55 +00003514 // If we have a ':', it's an alignment specifier.
3515 if (Parser.getTok().is(AsmToken::Colon)) {
3516 Parser.Lex(); // Eat the ':'.
3517 E = Parser.getTok().getLoc();
3518
3519 const MCExpr *Expr;
3520 if (getParser().ParseExpression(Expr))
3521 return true;
3522
3523 // The expression has to be a constant. Memory references with relocations
3524 // don't come through here, as they use the <label> forms of the relevant
3525 // instructions.
3526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3527 if (!CE)
3528 return Error (E, "constant expression expected");
3529
3530 unsigned Align = 0;
3531 switch (CE->getValue()) {
3532 default:
3533 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3534 case 64: Align = 8; break;
3535 case 128: Align = 16; break;
3536 case 256: Align = 32; break;
3537 }
3538
3539 // Now we should have the closing ']'
3540 E = Parser.getTok().getLoc();
3541 if (Parser.getTok().isNot(AsmToken::RBrac))
3542 return Error(E, "']' expected");
3543 Parser.Lex(); // Eat right bracket token.
3544
3545 // Don't worry about range checking the value here. That's handled by
3546 // the is*() predicates.
3547 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3548 ARM_AM::no_shift, 0, Align,
3549 false, S, E));
3550
3551 // If there's a pre-indexing writeback marker, '!', just add it as a token
3552 // operand.
3553 if (Parser.getTok().is(AsmToken::Exclaim)) {
3554 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3555 Parser.Lex(); // Eat the '!'.
3556 }
3557
3558 return false;
3559 }
3560
3561 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003562 // offset.
3563 if (Parser.getTok().is(AsmToken::Hash)) {
3564 Parser.Lex(); // Eat the '#'.
3565 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003566
Owen Anderson0da10cf2011-08-29 19:36:44 +00003567 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003568 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003569 if (getParser().ParseExpression(Offset))
3570 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003571
3572 // The expression has to be a constant. Memory references with relocations
3573 // don't come through here, as they use the <label> forms of the relevant
3574 // instructions.
3575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3576 if (!CE)
3577 return Error (E, "constant expression expected");
3578
Owen Anderson0da10cf2011-08-29 19:36:44 +00003579 // If the constant was #-0, represent it as INT32_MIN.
3580 int32_t Val = CE->getValue();
3581 if (isNegative && Val == 0)
3582 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3583
Jim Grosbach7ce05792011-08-03 23:50:40 +00003584 // Now we should have the closing ']'
3585 E = Parser.getTok().getLoc();
3586 if (Parser.getTok().isNot(AsmToken::RBrac))
3587 return Error(E, "']' expected");
3588 Parser.Lex(); // Eat right bracket token.
3589
3590 // Don't worry about range checking the value here. That's handled by
3591 // the is*() predicates.
3592 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003593 ARM_AM::no_shift, 0, 0,
3594 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003595
3596 // If there's a pre-indexing writeback marker, '!', just add it as a token
3597 // operand.
3598 if (Parser.getTok().is(AsmToken::Exclaim)) {
3599 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3600 Parser.Lex(); // Eat the '!'.
3601 }
3602
3603 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003604 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003605
3606 // The register offset is optionally preceded by a '+' or '-'
3607 bool isNegative = false;
3608 if (Parser.getTok().is(AsmToken::Minus)) {
3609 isNegative = true;
3610 Parser.Lex(); // Eat the '-'.
3611 } else if (Parser.getTok().is(AsmToken::Plus)) {
3612 // Nothing to do.
3613 Parser.Lex(); // Eat the '+'.
3614 }
3615
3616 E = Parser.getTok().getLoc();
3617 int OffsetRegNum = tryParseRegister();
3618 if (OffsetRegNum == -1)
3619 return Error(E, "register expected");
3620
3621 // If there's a shift operator, handle it.
3622 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003623 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003624 if (Parser.getTok().is(AsmToken::Comma)) {
3625 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003626 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627 return true;
3628 }
3629
3630 // Now we should have the closing ']'
3631 E = Parser.getTok().getLoc();
3632 if (Parser.getTok().isNot(AsmToken::RBrac))
3633 return Error(E, "']' expected");
3634 Parser.Lex(); // Eat right bracket token.
3635
3636 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003637 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003638 S, E));
3639
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003640 // If there's a pre-indexing writeback marker, '!', just add it as a token
3641 // operand.
3642 if (Parser.getTok().is(AsmToken::Exclaim)) {
3643 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3644 Parser.Lex(); // Eat the '!'.
3645 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003646
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003647 return false;
3648}
3649
Jim Grosbach7ce05792011-08-03 23:50:40 +00003650/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003651/// ( lsl | lsr | asr | ror ) , # shift_amount
3652/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003653/// return true if it parses a shift otherwise it returns false.
3654bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3655 unsigned &Amount) {
3656 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003657 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003658 if (Tok.isNot(AsmToken::Identifier))
3659 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003660 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003661 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003662 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003663 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003664 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003665 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003666 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003667 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003668 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003669 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003670 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003671 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003672 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003673 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003674
Jim Grosbach7ce05792011-08-03 23:50:40 +00003675 // rrx stands alone.
3676 Amount = 0;
3677 if (St != ARM_AM::rrx) {
3678 Loc = Parser.getTok().getLoc();
3679 // A '#' and a shift amount.
3680 const AsmToken &HashTok = Parser.getTok();
3681 if (HashTok.isNot(AsmToken::Hash))
3682 return Error(HashTok.getLoc(), "'#' expected");
3683 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003684
Jim Grosbach7ce05792011-08-03 23:50:40 +00003685 const MCExpr *Expr;
3686 if (getParser().ParseExpression(Expr))
3687 return true;
3688 // Range check the immediate.
3689 // lsl, ror: 0 <= imm <= 31
3690 // lsr, asr: 0 <= imm <= 32
3691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3692 if (!CE)
3693 return Error(Loc, "shift amount must be an immediate");
3694 int64_t Imm = CE->getValue();
3695 if (Imm < 0 ||
3696 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3697 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3698 return Error(Loc, "immediate shift value out of range");
3699 Amount = Imm;
3700 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003701
3702 return false;
3703}
3704
Jim Grosbach9d390362011-10-03 23:38:36 +00003705/// parseFPImm - A floating point immediate expression operand.
3706ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3707parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3708 SMLoc S = Parser.getTok().getLoc();
3709
3710 if (Parser.getTok().isNot(AsmToken::Hash))
3711 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003712
3713 // Disambiguate the VMOV forms that can accept an FP immediate.
3714 // vmov.f32 <sreg>, #imm
3715 // vmov.f64 <dreg>, #imm
3716 // vmov.f32 <dreg>, #imm @ vector f32x2
3717 // vmov.f32 <qreg>, #imm @ vector f32x4
3718 //
3719 // There are also the NEON VMOV instructions which expect an
3720 // integer constant. Make sure we don't try to parse an FPImm
3721 // for these:
3722 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3723 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3724 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3725 TyOp->getToken() != ".f64"))
3726 return MatchOperand_NoMatch;
3727
Jim Grosbach9d390362011-10-03 23:38:36 +00003728 Parser.Lex(); // Eat the '#'.
3729
3730 // Handle negation, as that still comes through as a separate token.
3731 bool isNegative = false;
3732 if (Parser.getTok().is(AsmToken::Minus)) {
3733 isNegative = true;
3734 Parser.Lex();
3735 }
3736 const AsmToken &Tok = Parser.getTok();
3737 if (Tok.is(AsmToken::Real)) {
3738 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3739 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3740 // If we had a '-' in front, toggle the sign bit.
3741 IntVal ^= (uint64_t)isNegative << 63;
3742 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3743 Parser.Lex(); // Eat the token.
3744 if (Val == -1) {
3745 TokError("floating point value out of range");
3746 return MatchOperand_ParseFail;
3747 }
3748 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3749 return MatchOperand_Success;
3750 }
3751 if (Tok.is(AsmToken::Integer)) {
3752 int64_t Val = Tok.getIntVal();
3753 Parser.Lex(); // Eat the token.
3754 if (Val > 255 || Val < 0) {
3755 TokError("encoded floating point value out of range");
3756 return MatchOperand_ParseFail;
3757 }
3758 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3759 return MatchOperand_Success;
3760 }
3761
3762 TokError("invalid floating point immediate");
3763 return MatchOperand_ParseFail;
3764}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003765/// Parse a arm instruction operand. For now this parses the operand regardless
3766/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003767bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003768 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003769 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003770
3771 // Check if the current operand has a custom associated parser, if so, try to
3772 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003773 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3774 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003775 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003776 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3777 // there was a match, but an error occurred, in which case, just return that
3778 // the operand parsing failed.
3779 if (ResTy == MatchOperand_ParseFail)
3780 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003781
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003782 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003783 default:
3784 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003785 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003786 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003787 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003788 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003789 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003790 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003791 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003792 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003793 else if (Res == -1) // irrecoverable error
3794 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003795 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3796 S = Parser.getTok().getLoc();
3797 Parser.Lex();
3798 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3799 return false;
3800 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003801
3802 // Fall though for the Identifier case that is not a register or a
3803 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003804 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003805 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003806 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003807 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003808 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003809 // This was not a register so parse other operands that start with an
3810 // identifier (like labels) as expressions and create them as immediates.
3811 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003812 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003813 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003814 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003815 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003816 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3817 return false;
3818 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003819 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003820 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003821 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003822 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003823 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003824 // #42 -> immediate.
3825 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003826 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003827 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003828 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003829 const MCExpr *ImmVal;
3830 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003831 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003832 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003833 if (CE) {
3834 int32_t Val = CE->getValue();
3835 if (isNegative && Val == 0)
3836 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003837 }
Sean Callanan76264762010-04-02 22:27:05 +00003838 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003839 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3840 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003841 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003842 case AsmToken::Colon: {
3843 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003844 // FIXME: Check it's an expression prefix,
3845 // e.g. (FOO - :lower16:BAR) isn't legal.
3846 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003847 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003848 return true;
3849
Evan Cheng75972122011-01-13 07:58:56 +00003850 const MCExpr *SubExprVal;
3851 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003852 return true;
3853
Evan Cheng75972122011-01-13 07:58:56 +00003854 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3855 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003856 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003857 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003858 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003859 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003860 }
3861}
3862
Jim Grosbach1355cf12011-07-26 17:10:22 +00003863// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003864// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003865bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003866 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003867
3868 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003869 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003870 Parser.Lex(); // Eat ':'
3871
3872 if (getLexer().isNot(AsmToken::Identifier)) {
3873 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3874 return true;
3875 }
3876
3877 StringRef IDVal = Parser.getTok().getIdentifier();
3878 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003879 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003880 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003881 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003882 } else {
3883 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3884 return true;
3885 }
3886 Parser.Lex();
3887
3888 if (getLexer().isNot(AsmToken::Colon)) {
3889 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3890 return true;
3891 }
3892 Parser.Lex(); // Eat the last ':'
3893 return false;
3894}
3895
Daniel Dunbar352e1482011-01-11 15:59:50 +00003896/// \brief Given a mnemonic, split out possible predication code and carry
3897/// setting letters to form a canonical mnemonic and flags.
3898//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003899// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003900// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003901StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003902 unsigned &PredicationCode,
3903 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003904 unsigned &ProcessorIMod,
3905 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003906 PredicationCode = ARMCC::AL;
3907 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003908 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003909
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003910 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003911 //
3912 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003913 if ((Mnemonic == "movs" && isThumb()) ||
3914 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3915 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3916 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3917 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3918 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3919 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3920 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003921 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003922
Jim Grosbach3f00e312011-07-11 17:09:57 +00003923 // First, split out any predication code. Ignore mnemonics we know aren't
3924 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003925 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003926 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003927 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003928 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003929 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3930 .Case("eq", ARMCC::EQ)
3931 .Case("ne", ARMCC::NE)
3932 .Case("hs", ARMCC::HS)
3933 .Case("cs", ARMCC::HS)
3934 .Case("lo", ARMCC::LO)
3935 .Case("cc", ARMCC::LO)
3936 .Case("mi", ARMCC::MI)
3937 .Case("pl", ARMCC::PL)
3938 .Case("vs", ARMCC::VS)
3939 .Case("vc", ARMCC::VC)
3940 .Case("hi", ARMCC::HI)
3941 .Case("ls", ARMCC::LS)
3942 .Case("ge", ARMCC::GE)
3943 .Case("lt", ARMCC::LT)
3944 .Case("gt", ARMCC::GT)
3945 .Case("le", ARMCC::LE)
3946 .Case("al", ARMCC::AL)
3947 .Default(~0U);
3948 if (CC != ~0U) {
3949 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3950 PredicationCode = CC;
3951 }
Bill Wendling52925b62010-10-29 23:50:21 +00003952 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003953
Daniel Dunbar352e1482011-01-11 15:59:50 +00003954 // Next, determine if we have a carry setting bit. We explicitly ignore all
3955 // the instructions we know end in 's'.
3956 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003957 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003958 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3959 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3960 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003961 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3962 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003963 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3964 CarrySetting = true;
3965 }
3966
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003967 // The "cps" instruction can have a interrupt mode operand which is glued into
3968 // the mnemonic. Check if this is the case, split it and parse the imod op
3969 if (Mnemonic.startswith("cps")) {
3970 // Split out any imod code.
3971 unsigned IMod =
3972 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3973 .Case("ie", ARM_PROC::IE)
3974 .Case("id", ARM_PROC::ID)
3975 .Default(~0U);
3976 if (IMod != ~0U) {
3977 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3978 ProcessorIMod = IMod;
3979 }
3980 }
3981
Jim Grosbach89df9962011-08-26 21:43:41 +00003982 // The "it" instruction has the condition mask on the end of the mnemonic.
3983 if (Mnemonic.startswith("it")) {
3984 ITMask = Mnemonic.slice(2, Mnemonic.size());
3985 Mnemonic = Mnemonic.slice(0, 2);
3986 }
3987
Daniel Dunbar352e1482011-01-11 15:59:50 +00003988 return Mnemonic;
3989}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003990
3991/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3992/// inclusion of carry set or predication code operands.
3993//
3994// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003995void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003996getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003997 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003998 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3999 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004000 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004001 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004002 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004003 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004004 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004005 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004006 Mnemonic == "mla" || Mnemonic == "smlal" ||
4007 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004008 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004009 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004010 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004011
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004012 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4013 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4014 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4015 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004016 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4017 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004018 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004019 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4020 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4021 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004022 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4023 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004024 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004025 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004026 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004027 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004028
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004029 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004030 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004031 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004032 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004033 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004034}
4035
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004036bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4037 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004038 // FIXME: This is all horribly hacky. We really need a better way to deal
4039 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004040
4041 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4042 // another does not. Specifically, the MOVW instruction does not. So we
4043 // special case it here and remove the defaulted (non-setting) cc_out
4044 // operand if that's the instruction we're trying to match.
4045 //
4046 // We do this as post-processing of the explicit operands rather than just
4047 // conditionally adding the cc_out in the first place because we need
4048 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004049 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004050 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4051 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4052 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4053 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004054
4055 // Register-register 'add' for thumb does not have a cc_out operand
4056 // when there are only two register operands.
4057 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4058 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4059 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4060 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4061 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004062 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004063 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4064 // have to check the immediate range here since Thumb2 has a variant
4065 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004066 if (((isThumb() && Mnemonic == "add") ||
4067 (isThumbTwo() && Mnemonic == "sub")) &&
4068 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004069 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4070 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4071 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004072 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4073 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4074 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004075 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004076 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4077 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004078 // selecting via the generic "add" mnemonic, so to know that we
4079 // should remove the cc_out operand, we have to explicitly check that
4080 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004081 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4082 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004083 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4084 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4085 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4086 // Nest conditions rather than one big 'if' statement for readability.
4087 //
4088 // If either register is a high reg, it's either one of the SP
4089 // variants (handled above) or a 32-bit encoding, so we just
4090 // check against T3.
4091 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4092 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4093 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4094 return false;
4095 // If both registers are low, we're in an IT block, and the immediate is
4096 // in range, we should use encoding T1 instead, which has a cc_out.
4097 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004098 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004099 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4100 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4101 return false;
4102
4103 // Otherwise, we use encoding T4, which does not have a cc_out
4104 // operand.
4105 return true;
4106 }
4107
Jim Grosbach64944f42011-09-14 21:00:40 +00004108 // The thumb2 multiply instruction doesn't have a CCOut register, so
4109 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4110 // use the 16-bit encoding or not.
4111 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4112 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4113 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4114 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4115 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4116 // If the registers aren't low regs, the destination reg isn't the
4117 // same as one of the source regs, or the cc_out operand is zero
4118 // outside of an IT block, we have to use the 32-bit encoding, so
4119 // remove the cc_out operand.
4120 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4121 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004122 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004123 !inITBlock() ||
4124 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4125 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4126 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4127 static_cast<ARMOperand*>(Operands[4])->getReg())))
4128 return true;
4129
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004130 // Also check the 'mul' syntax variant that doesn't specify an explicit
4131 // destination register.
4132 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4133 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4134 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4135 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4136 // If the registers aren't low regs or the cc_out operand is zero
4137 // outside of an IT block, we have to use the 32-bit encoding, so
4138 // remove the cc_out operand.
4139 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4140 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4141 !inITBlock()))
4142 return true;
4143
Jim Grosbach64944f42011-09-14 21:00:40 +00004144
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004145
Jim Grosbachf69c8042011-08-24 21:42:27 +00004146 // Register-register 'add/sub' for thumb does not have a cc_out operand
4147 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4148 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4149 // right, this will result in better diagnostics (which operand is off)
4150 // anyway.
4151 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4152 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004153 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4154 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4155 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4156 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004157
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004158 return false;
4159}
4160
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004161static bool isDataTypeToken(StringRef Tok) {
4162 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4163 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4164 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4165 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4166 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4167 Tok == ".f" || Tok == ".d";
4168}
4169
4170// FIXME: This bit should probably be handled via an explicit match class
4171// in the .td files that matches the suffix instead of having it be
4172// a literal string token the way it is now.
4173static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4174 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4175}
4176
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004177/// Parse an arm instruction mnemonic followed by its operands.
4178bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4179 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4180 // Create the leading tokens for the mnemonic, split by '.' characters.
4181 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004182 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004183
Daniel Dunbar352e1482011-01-11 15:59:50 +00004184 // Split out the predication code and carry setting flag from the mnemonic.
4185 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004186 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004187 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004188 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004189 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004190 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004191
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004192 // In Thumb1, only the branch (B) instruction can be predicated.
4193 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4194 Parser.EatToEndOfStatement();
4195 return Error(NameLoc, "conditional execution not supported in Thumb1");
4196 }
4197
Jim Grosbachffa32252011-07-19 19:13:28 +00004198 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4199
Jim Grosbach89df9962011-08-26 21:43:41 +00004200 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4201 // is the mask as it will be for the IT encoding if the conditional
4202 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4203 // where the conditional bit0 is zero, the instruction post-processing
4204 // will adjust the mask accordingly.
4205 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004206 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4207 if (ITMask.size() > 3) {
4208 Parser.EatToEndOfStatement();
4209 return Error(Loc, "too many conditions on IT instruction");
4210 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004211 unsigned Mask = 8;
4212 for (unsigned i = ITMask.size(); i != 0; --i) {
4213 char pos = ITMask[i - 1];
4214 if (pos != 't' && pos != 'e') {
4215 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004216 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004217 }
4218 Mask >>= 1;
4219 if (ITMask[i - 1] == 't')
4220 Mask |= 8;
4221 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004222 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004223 }
4224
Jim Grosbachffa32252011-07-19 19:13:28 +00004225 // FIXME: This is all a pretty gross hack. We should automatically handle
4226 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004227
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004228 // Next, add the CCOut and ConditionCode operands, if needed.
4229 //
4230 // For mnemonics which can ever incorporate a carry setting bit or predication
4231 // code, our matching model involves us always generating CCOut and
4232 // ConditionCode operands to match the mnemonic "as written" and then we let
4233 // the matcher deal with finding the right instruction or generating an
4234 // appropriate error.
4235 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004236 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004237
Jim Grosbach33c16a22011-07-14 22:04:21 +00004238 // If we had a carry-set on an instruction that can't do that, issue an
4239 // error.
4240 if (!CanAcceptCarrySet && CarrySetting) {
4241 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004242 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004243 "' can not set flags, but 's' suffix specified");
4244 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004245 // If we had a predication code on an instruction that can't do that, issue an
4246 // error.
4247 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4248 Parser.EatToEndOfStatement();
4249 return Error(NameLoc, "instruction '" + Mnemonic +
4250 "' is not predicable, but condition code specified");
4251 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004252
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004253 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004254 if (CanAcceptCarrySet) {
4255 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004256 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004257 Loc));
4258 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004259
4260 // Add the predication code operand, if necessary.
4261 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004262 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4263 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004264 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004265 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004266 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004267
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004268 // Add the processor imod operand, if necessary.
4269 if (ProcessorIMod) {
4270 Operands.push_back(ARMOperand::CreateImm(
4271 MCConstantExpr::Create(ProcessorIMod, getContext()),
4272 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004273 }
4274
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004275 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004276 while (Next != StringRef::npos) {
4277 Start = Next;
4278 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004279 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004280
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004281 // Some NEON instructions have an optional datatype suffix that is
4282 // completely ignored. Check for that.
4283 if (isDataTypeToken(ExtraToken) &&
4284 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4285 continue;
4286
Jim Grosbach81d2e392011-09-07 16:06:04 +00004287 if (ExtraToken != ".n") {
4288 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4289 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4290 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004291 }
4292
4293 // Read the remaining operands.
4294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004295 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004296 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004297 Parser.EatToEndOfStatement();
4298 return true;
4299 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004300
4301 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004302 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004303
4304 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004305 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004306 Parser.EatToEndOfStatement();
4307 return true;
4308 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004309 }
4310 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004311
Chris Lattnercbf8a982010-09-11 16:18:25 +00004312 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004313 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004314 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004315 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004316 }
Bill Wendling146018f2010-11-06 21:42:12 +00004317
Chris Lattner34e53142010-09-08 05:10:46 +00004318 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004319
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004320 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4321 // do and don't have a cc_out optional-def operand. With some spot-checks
4322 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004323 // parse and adjust accordingly before actually matching. We shouldn't ever
4324 // try to remove a cc_out operand that was explicitly set on the the
4325 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4326 // table driven matcher doesn't fit well with the ARM instruction set.
4327 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004328 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4329 Operands.erase(Operands.begin() + 1);
4330 delete Op;
4331 }
4332
Jim Grosbachcf121c32011-07-28 21:57:55 +00004333 // ARM mode 'blx' need special handling, as the register operand version
4334 // is predicable, but the label operand version is not. So, we can't rely
4335 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004336 // a k_CondCode operand in the list. If we're trying to match the label
4337 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004338 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4339 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4340 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4341 Operands.erase(Operands.begin() + 1);
4342 delete Op;
4343 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004344
4345 // The vector-compare-to-zero instructions have a literal token "#0" at
4346 // the end that comes to here as an immediate operand. Convert it to a
4347 // token to play nicely with the matcher.
4348 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4349 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4350 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4351 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4352 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4353 if (CE && CE->getValue() == 0) {
4354 Operands.erase(Operands.begin() + 5);
4355 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4356 delete Op;
4357 }
4358 }
Jim Grosbach68259142011-10-03 22:30:24 +00004359 // VCMP{E} does the same thing, but with a different operand count.
4360 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4361 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4362 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4363 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4364 if (CE && CE->getValue() == 0) {
4365 Operands.erase(Operands.begin() + 4);
4366 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4367 delete Op;
4368 }
4369 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004370 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4371 // end. Convert it to a token here.
4372 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4373 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4374 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4375 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4376 if (CE && CE->getValue() == 0) {
4377 Operands.erase(Operands.begin() + 5);
4378 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4379 delete Op;
4380 }
4381 }
4382
Chris Lattner98986712010-01-14 22:21:20 +00004383 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004384}
4385
Jim Grosbach189610f2011-07-26 18:25:39 +00004386// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004387
4388// return 'true' if register list contains non-low GPR registers,
4389// 'false' otherwise. If Reg is in the register list or is HiReg, set
4390// 'containsReg' to true.
4391static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4392 unsigned HiReg, bool &containsReg) {
4393 containsReg = false;
4394 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4395 unsigned OpReg = Inst.getOperand(i).getReg();
4396 if (OpReg == Reg)
4397 containsReg = true;
4398 // Anything other than a low register isn't legal here.
4399 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4400 return true;
4401 }
4402 return false;
4403}
4404
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004405// Check if the specified regisgter is in the register list of the inst,
4406// starting at the indicated operand number.
4407static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4408 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4409 unsigned OpReg = Inst.getOperand(i).getReg();
4410 if (OpReg == Reg)
4411 return true;
4412 }
4413 return false;
4414}
4415
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004416// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4417// the ARMInsts array) instead. Getting that here requires awkward
4418// API changes, though. Better way?
4419namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004420extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004421}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004422static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004423 return ARMInsts[Opcode];
4424}
4425
Jim Grosbach189610f2011-07-26 18:25:39 +00004426// FIXME: We would really like to be able to tablegen'erate this.
4427bool ARMAsmParser::
4428validateInstruction(MCInst &Inst,
4429 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004430 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004431 SMLoc Loc = Operands[0]->getStartLoc();
4432 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004433 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4434 // being allowed in IT blocks, but not being predicable. It just always
4435 // executes.
4436 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004437 unsigned bit = 1;
4438 if (ITState.FirstCond)
4439 ITState.FirstCond = false;
4440 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004441 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004442 // The instruction must be predicable.
4443 if (!MCID.isPredicable())
4444 return Error(Loc, "instructions in IT block must be predicable");
4445 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4446 unsigned ITCond = bit ? ITState.Cond :
4447 ARMCC::getOppositeCondition(ITState.Cond);
4448 if (Cond != ITCond) {
4449 // Find the condition code Operand to get its SMLoc information.
4450 SMLoc CondLoc;
4451 for (unsigned i = 1; i < Operands.size(); ++i)
4452 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4453 CondLoc = Operands[i]->getStartLoc();
4454 return Error(CondLoc, "incorrect condition in IT block; got '" +
4455 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4456 "', but expected '" +
4457 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4458 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004459 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004460 } else if (isThumbTwo() && MCID.isPredicable() &&
4461 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004462 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4463 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004464 return Error(Loc, "predicated instructions must be in IT block");
4465
Jim Grosbach189610f2011-07-26 18:25:39 +00004466 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004467 case ARM::LDRD:
4468 case ARM::LDRD_PRE:
4469 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004470 case ARM::LDREXD: {
4471 // Rt2 must be Rt + 1.
4472 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4473 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4474 if (Rt2 != Rt + 1)
4475 return Error(Operands[3]->getStartLoc(),
4476 "destination operands must be sequential");
4477 return false;
4478 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004479 case ARM::STRD: {
4480 // Rt2 must be Rt + 1.
4481 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4482 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4483 if (Rt2 != Rt + 1)
4484 return Error(Operands[3]->getStartLoc(),
4485 "source operands must be sequential");
4486 return false;
4487 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004488 case ARM::STRD_PRE:
4489 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004490 case ARM::STREXD: {
4491 // Rt2 must be Rt + 1.
4492 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4493 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4494 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004495 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004496 "source operands must be sequential");
4497 return false;
4498 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004499 case ARM::SBFX:
4500 case ARM::UBFX: {
4501 // width must be in range [1, 32-lsb]
4502 unsigned lsb = Inst.getOperand(2).getImm();
4503 unsigned widthm1 = Inst.getOperand(3).getImm();
4504 if (widthm1 >= 32 - lsb)
4505 return Error(Operands[5]->getStartLoc(),
4506 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004507 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004508 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004509 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004510 // If we're parsing Thumb2, the .w variant is available and handles
4511 // most cases that are normally illegal for a Thumb1 LDM
4512 // instruction. We'll make the transformation in processInstruction()
4513 // if necessary.
4514 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004515 // Thumb LDM instructions are writeback iff the base register is not
4516 // in the register list.
4517 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004518 bool hasWritebackToken =
4519 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4520 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004521 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004522 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004523 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4524 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004525 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004526 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004527 return Error(Operands[2]->getStartLoc(),
4528 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004529 // If we should not have writeback, there must not be a '!'. This is
4530 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004531 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004532 return Error(Operands[3]->getStartLoc(),
4533 "writeback operator '!' not allowed when base register "
4534 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004535
4536 break;
4537 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004538 case ARM::t2LDMIA_UPD: {
4539 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4540 return Error(Operands[4]->getStartLoc(),
4541 "writeback operator '!' not allowed when base register "
4542 "in register list");
4543 break;
4544 }
Jim Grosbach54026372011-11-10 23:17:11 +00004545 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4546 // so only issue a diagnostic for thumb1. The instructions will be
4547 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004548 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004549 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004550 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4551 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004552 return Error(Operands[2]->getStartLoc(),
4553 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004554 break;
4555 }
4556 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004557 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004558 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4559 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004560 return Error(Operands[2]->getStartLoc(),
4561 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004562 break;
4563 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004564 case ARM::tSTMIA_UPD: {
4565 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004566 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004567 return Error(Operands[4]->getStartLoc(),
4568 "registers must be in range r0-r7");
4569 break;
4570 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004571 }
4572
4573 return false;
4574}
4575
Jim Grosbach83ec8772011-11-10 23:42:14 +00004576bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004577processInstruction(MCInst &Inst,
4578 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4579 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004580 // Handle the MOV complex aliases.
Jim Grosbachee10ff82011-11-10 19:18:01 +00004581 case ARM::ASRi:
4582 case ARM::LSRi:
4583 case ARM::LSLi:
4584 case ARM::RORi: {
4585 ARM_AM::ShiftOpc ShiftTy;
4586 unsigned Amt = Inst.getOperand(2).getImm();
4587 switch(Inst.getOpcode()) {
4588 default: llvm_unreachable("unexpected opcode!");
4589 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4590 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4591 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4592 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4593 }
4594 // A shift by zero is a plain MOVr, not a MOVsi.
4595 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4596 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004597 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004598 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004599 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4600 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004601 if (Opc == ARM::MOVsi)
4602 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004603 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4604 TmpInst.addOperand(Inst.getOperand(4));
4605 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4606 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004607 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004608 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004609 case ARM::t2LDMIA_UPD: {
4610 // If this is a load of a single register, then we should use
4611 // a post-indexed LDR instruction instead, per the ARM ARM.
4612 if (Inst.getNumOperands() != 5)
4613 return false;
4614 MCInst TmpInst;
4615 TmpInst.setOpcode(ARM::t2LDR_POST);
4616 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4617 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4618 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4619 TmpInst.addOperand(MCOperand::CreateImm(4));
4620 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4621 TmpInst.addOperand(Inst.getOperand(3));
4622 Inst = TmpInst;
4623 return true;
4624 }
4625 case ARM::t2STMDB_UPD: {
4626 // If this is a store of a single register, then we should use
4627 // a pre-indexed STR instruction instead, per the ARM ARM.
4628 if (Inst.getNumOperands() != 5)
4629 return false;
4630 MCInst TmpInst;
4631 TmpInst.setOpcode(ARM::t2STR_PRE);
4632 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4633 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4634 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4635 TmpInst.addOperand(MCOperand::CreateImm(-4));
4636 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4637 TmpInst.addOperand(Inst.getOperand(3));
4638 Inst = TmpInst;
4639 return true;
4640 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004641 case ARM::LDMIA_UPD:
4642 // If this is a load of a single register via a 'pop', then we should use
4643 // a post-indexed LDR instruction instead, per the ARM ARM.
4644 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4645 Inst.getNumOperands() == 5) {
4646 MCInst TmpInst;
4647 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4648 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4649 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4650 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4651 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4652 TmpInst.addOperand(MCOperand::CreateImm(4));
4653 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4654 TmpInst.addOperand(Inst.getOperand(3));
4655 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004656 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004657 }
4658 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004659 case ARM::STMDB_UPD:
4660 // If this is a store of a single register via a 'push', then we should use
4661 // a pre-indexed STR instruction instead, per the ARM ARM.
4662 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4663 Inst.getNumOperands() == 5) {
4664 MCInst TmpInst;
4665 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4666 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4667 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4668 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4669 TmpInst.addOperand(MCOperand::CreateImm(-4));
4670 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4671 TmpInst.addOperand(Inst.getOperand(3));
4672 Inst = TmpInst;
4673 }
4674 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004675 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004676 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4677 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4678 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4679 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004680 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004681 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004682 return true;
4683 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004684 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004685 case ARM::tSUBi8:
4686 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4687 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4688 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4689 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004690 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004691 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004692 return true;
4693 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004694 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004695 case ARM::tB:
4696 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004697 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004698 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004699 return true;
4700 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004701 break;
4702 case ARM::t2B:
4703 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004704 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004705 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004706 return true;
4707 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004708 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004709 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004710 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004711 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004712 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004713 return true;
4714 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004715 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004716 case ARM::tBcc:
4717 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004718 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004719 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004720 return true;
4721 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004722 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004723 case ARM::tLDMIA: {
4724 // If the register list contains any high registers, or if the writeback
4725 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4726 // instead if we're in Thumb2. Otherwise, this should have generated
4727 // an error in validateInstruction().
4728 unsigned Rn = Inst.getOperand(0).getReg();
4729 bool hasWritebackToken =
4730 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4731 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4732 bool listContainsBase;
4733 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4734 (!listContainsBase && !hasWritebackToken) ||
4735 (listContainsBase && hasWritebackToken)) {
4736 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4737 assert (isThumbTwo());
4738 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4739 // If we're switching to the updating version, we need to insert
4740 // the writeback tied operand.
4741 if (hasWritebackToken)
4742 Inst.insert(Inst.begin(),
4743 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004744 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004745 }
4746 break;
4747 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004748 case ARM::tSTMIA_UPD: {
4749 // If the register list contains any high registers, we need to use
4750 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4751 // should have generated an error in validateInstruction().
4752 unsigned Rn = Inst.getOperand(0).getReg();
4753 bool listContainsBase;
4754 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4755 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4756 assert (isThumbTwo());
4757 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004758 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004759 }
4760 break;
4761 }
Jim Grosbach54026372011-11-10 23:17:11 +00004762 case ARM::tPOP: {
4763 bool listContainsBase;
4764 // If the register list contains any high registers, we need to use
4765 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4766 // should have generated an error in validateInstruction().
4767 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004768 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004769 assert (isThumbTwo());
4770 Inst.setOpcode(ARM::t2LDMIA_UPD);
4771 // Add the base register and writeback operands.
4772 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4773 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004774 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004775 }
4776 case ARM::tPUSH: {
4777 bool listContainsBase;
4778 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004779 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004780 assert (isThumbTwo());
4781 Inst.setOpcode(ARM::t2STMDB_UPD);
4782 // Add the base register and writeback operands.
4783 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4784 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004785 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004786 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004787 case ARM::t2MOVi: {
4788 // If we can use the 16-bit encoding and the user didn't explicitly
4789 // request the 32-bit variant, transform it here.
4790 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4791 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004792 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4793 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4794 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004795 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4796 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4797 // The operands aren't in the same order for tMOVi8...
4798 MCInst TmpInst;
4799 TmpInst.setOpcode(ARM::tMOVi8);
4800 TmpInst.addOperand(Inst.getOperand(0));
4801 TmpInst.addOperand(Inst.getOperand(4));
4802 TmpInst.addOperand(Inst.getOperand(1));
4803 TmpInst.addOperand(Inst.getOperand(2));
4804 TmpInst.addOperand(Inst.getOperand(3));
4805 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004806 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004807 }
4808 break;
4809 }
4810 case ARM::t2MOVr: {
4811 // If we can use the 16-bit encoding and the user didn't explicitly
4812 // request the 32-bit variant, transform it here.
4813 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4814 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4815 Inst.getOperand(2).getImm() == ARMCC::AL &&
4816 Inst.getOperand(4).getReg() == ARM::CPSR &&
4817 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4818 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4819 // The operands aren't the same for tMOV[S]r... (no cc_out)
4820 MCInst TmpInst;
4821 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4822 TmpInst.addOperand(Inst.getOperand(0));
4823 TmpInst.addOperand(Inst.getOperand(1));
4824 TmpInst.addOperand(Inst.getOperand(2));
4825 TmpInst.addOperand(Inst.getOperand(3));
4826 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004827 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004828 }
4829 break;
4830 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004831 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004832 case ARM::t2SXTB:
4833 case ARM::t2UXTH:
4834 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004835 // If we can use the 16-bit encoding and the user didn't explicitly
4836 // request the 32-bit variant, transform it here.
4837 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4838 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4839 Inst.getOperand(2).getImm() == 0 &&
4840 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4841 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004842 unsigned NewOpc;
4843 switch (Inst.getOpcode()) {
4844 default: llvm_unreachable("Illegal opcode!");
4845 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4846 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4847 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4848 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4849 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004850 // The operands aren't the same for thumb1 (no rotate operand).
4851 MCInst TmpInst;
4852 TmpInst.setOpcode(NewOpc);
4853 TmpInst.addOperand(Inst.getOperand(0));
4854 TmpInst.addOperand(Inst.getOperand(1));
4855 TmpInst.addOperand(Inst.getOperand(3));
4856 TmpInst.addOperand(Inst.getOperand(4));
4857 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004858 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00004859 }
4860 break;
4861 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004862 case ARM::t2IT: {
4863 // The mask bits for all but the first condition are represented as
4864 // the low bit of the condition code value implies 't'. We currently
4865 // always have 1 implies 't', so XOR toggle the bits if the low bit
4866 // of the condition code is zero. The encoding also expects the low
4867 // bit of the condition to be encoded as bit 4 of the mask operand,
4868 // so mask that in if needed
4869 MCOperand &MO = Inst.getOperand(1);
4870 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004871 unsigned OrigMask = Mask;
4872 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004873 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004874 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4875 for (unsigned i = 3; i != TZ; --i)
4876 Mask ^= 1 << i;
4877 } else
4878 Mask |= 0x10;
4879 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004880
4881 // Set up the IT block state according to the IT instruction we just
4882 // matched.
4883 assert(!inITBlock() && "nested IT blocks?!");
4884 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4885 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4886 ITState.CurPosition = 0;
4887 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004888 break;
4889 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004890 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00004891 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004892}
4893
Jim Grosbach47a0d522011-08-16 20:45:50 +00004894unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4895 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4896 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004897 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004898 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004899 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4900 assert(MCID.hasOptionalDef() &&
4901 "optionally flag setting instruction missing optional def operand");
4902 assert(MCID.NumOperands == Inst.getNumOperands() &&
4903 "operand count mismatch!");
4904 // Find the optional-def operand (cc_out).
4905 unsigned OpNo;
4906 for (OpNo = 0;
4907 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4908 ++OpNo)
4909 ;
4910 // If we're parsing Thumb1, reject it completely.
4911 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4912 return Match_MnemonicFail;
4913 // If we're parsing Thumb2, which form is legal depends on whether we're
4914 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004915 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4916 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004917 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004918 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4919 inITBlock())
4920 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004921 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004922 // Some high-register supporting Thumb1 encodings only allow both registers
4923 // to be from r0-r7 when in Thumb2.
4924 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4925 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4926 isARMLowRegister(Inst.getOperand(2).getReg()))
4927 return Match_RequiresThumb2;
4928 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004929 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004930 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4931 isARMLowRegister(Inst.getOperand(1).getReg()))
4932 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004933 return Match_Success;
4934}
4935
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004936bool ARMAsmParser::
4937MatchAndEmitInstruction(SMLoc IDLoc,
4938 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4939 MCStreamer &Out) {
4940 MCInst Inst;
4941 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004942 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004943 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004944 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004945 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004946 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004947 // Context sensitive operand constraints aren't handled by the matcher,
4948 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004949 if (validateInstruction(Inst, Operands)) {
4950 // Still progress the IT block, otherwise one wrong condition causes
4951 // nasty cascading errors.
4952 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004953 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004954 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004955
Jim Grosbachf8fce712011-08-11 17:35:48 +00004956 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00004957 // encoding is selected. Loop on it while changes happen so the
4958 // individual transformations can chain off each other. E.g.,
4959 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
4960 while (processInstruction(Inst, Operands))
4961 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004962
Jim Grosbacha1109882011-09-02 23:22:08 +00004963 // Only move forward at the very end so that everything in validate
4964 // and process gets a consistent answer about whether we're in an IT
4965 // block.
4966 forwardITPosition();
4967
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004968 Out.EmitInstruction(Inst);
4969 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004970 case Match_MissingFeature:
4971 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4972 return true;
4973 case Match_InvalidOperand: {
4974 SMLoc ErrorLoc = IDLoc;
4975 if (ErrorInfo != ~0U) {
4976 if (ErrorInfo >= Operands.size())
4977 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004978
Chris Lattnere73d4f82010-10-28 21:41:58 +00004979 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4980 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4981 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004982
Chris Lattnere73d4f82010-10-28 21:41:58 +00004983 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004984 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004985 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004986 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004987 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004988 // The converter function will have already emited a diagnostic.
4989 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004990 case Match_RequiresNotITBlock:
4991 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004992 case Match_RequiresITBlock:
4993 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004994 case Match_RequiresV6:
4995 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4996 case Match_RequiresThumb2:
4997 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004998 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004999
Eric Christopherc223e2b2010-10-29 09:26:59 +00005000 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005001 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005002}
5003
Jim Grosbach1355cf12011-07-26 17:10:22 +00005004/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005005bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5006 StringRef IDVal = DirectiveID.getIdentifier();
5007 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005008 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005009 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005010 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005011 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005012 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005013 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005014 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005015 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005016 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005017 return true;
5018}
5019
Jim Grosbach1355cf12011-07-26 17:10:22 +00005020/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005021/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005022bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5024 for (;;) {
5025 const MCExpr *Value;
5026 if (getParser().ParseExpression(Value))
5027 return true;
5028
Chris Lattneraaec2052010-01-19 19:46:13 +00005029 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005030
5031 if (getLexer().is(AsmToken::EndOfStatement))
5032 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005033
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005034 // FIXME: Improve diagnostic.
5035 if (getLexer().isNot(AsmToken::Comma))
5036 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005037 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005038 }
5039 }
5040
Sean Callananb9a25b72010-01-19 20:27:46 +00005041 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005042 return false;
5043}
5044
Jim Grosbach1355cf12011-07-26 17:10:22 +00005045/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005046/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005047bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005048 if (getLexer().isNot(AsmToken::EndOfStatement))
5049 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005050 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005051
5052 // TODO: set thumb mode
5053 // TODO: tell the MC streamer the mode
5054 // getParser().getStreamer().Emit???();
5055 return false;
5056}
5057
Jim Grosbach1355cf12011-07-26 17:10:22 +00005058/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005059/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005060bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005061 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5062 bool isMachO = MAI.hasSubsectionsViaSymbols();
5063 StringRef Name;
5064
5065 // Darwin asm has function name after .thumb_func direction
5066 // ELF doesn't
5067 if (isMachO) {
5068 const AsmToken &Tok = Parser.getTok();
5069 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5070 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005071 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005072 Parser.Lex(); // Consume the identifier token.
5073 }
5074
Jim Grosbachd475f862011-11-10 20:48:53 +00005075 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005076 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005077 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005078
Rafael Espindola64695402011-05-16 16:17:21 +00005079 // FIXME: assuming function name will be the line following .thumb_func
5080 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005081 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005082 }
5083
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005084 // Mark symbol as a thumb symbol.
5085 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5086 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005087 return false;
5088}
5089
Jim Grosbach1355cf12011-07-26 17:10:22 +00005090/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005091/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005092bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005093 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005094 if (Tok.isNot(AsmToken::Identifier))
5095 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005096 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005097 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005098 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005099 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005100 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005101 else
5102 return Error(L, "unrecognized syntax mode in .syntax directive");
5103
5104 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005105 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005106 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005107
5108 // TODO tell the MC streamer the mode
5109 // getParser().getStreamer().Emit???();
5110 return false;
5111}
5112
Jim Grosbach1355cf12011-07-26 17:10:22 +00005113/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005114/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005115bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005116 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005117 if (Tok.isNot(AsmToken::Integer))
5118 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005119 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005120 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005121 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005122 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005123 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005124 else
5125 return Error(L, "invalid operand to .code directive");
5126
5127 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005128 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005129 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005130
Evan Cheng32869202011-07-08 22:36:29 +00005131 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005132 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005133 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005134 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005135 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005136 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005137 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005138 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005139 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005140
Kevin Enderby515d5092009-10-15 20:48:48 +00005141 return false;
5142}
5143
Sean Callanan90b70972010-04-07 20:29:34 +00005144extern "C" void LLVMInitializeARMAsmLexer();
5145
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005146/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005147extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005148 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5149 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005150 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005151}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005152
Chris Lattner0692ee62010-09-06 19:11:01 +00005153#define GET_REGISTER_MATCHER
5154#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005155#include "ARMGenAsmMatcher.inc"