blob: 501a1c89bbf0b1fe721fb7c1cb271e8174c9e23f [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Evan Cheng94b95502011-07-26 00:24:13 +000042class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000043 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000044 MCAsmParser &Parser;
45
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000046 struct {
47 ARMCC::CondCodes Cond; // Condition for IT block.
48 unsigned Mask:4; // Condition mask for instructions.
49 // Starting at first 1 (from lsb).
50 // '1' condition as indicated in IT.
51 // '0' inverse of condition (else).
52 // Count of instructions in IT block is
53 // 4 - trailingzeroes(mask)
54
55 bool FirstCond; // Explicit flag for when we're parsing the
56 // First instruction in the IT block. It's
57 // implied in the mask, so needs special
58 // handling.
59
60 unsigned CurPosition; // Current position in parsing of IT
61 // block. In range [0,3]. Initialized
62 // according to count of instructions in block.
63 // ~0U if no active IT block.
64 } ITState;
65 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000066 void forwardITPosition() {
67 if (!inITBlock()) return;
68 // Move to the next instruction in the IT block, if there is one. If not,
69 // mark the block as done.
70 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
71 if (++ITState.CurPosition == 5 - TZ)
72 ITState.CurPosition = ~0U; // Done with the IT block after this.
73 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000074
75
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000076 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
78
79 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000080 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
81
Jim Grosbach1355cf12011-07-26 17:10:22 +000082 int tryParseRegister();
83 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000084 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000085 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000086 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
88 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000089 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
90 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000091 bool parseDirectiveWord(unsigned Size, SMLoc L);
92 bool parseDirectiveThumb(SMLoc L);
93 bool parseDirectiveThumbFunc(SMLoc L);
94 bool parseDirectiveCode(SMLoc L);
95 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000096
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000098 bool &CarrySetting, unsigned &ProcessorIMod,
99 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000101 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000102
Evan Chengebdeeab2011-07-08 01:53:10 +0000103 bool isThumb() const {
104 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000105 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000110 bool isThumbTwo() const {
111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
112 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000113 bool hasV6Ops() const {
114 return STI.getFeatureBits() & ARM::HasV6Ops;
115 }
James Molloyacad68d2011-09-28 14:21:38 +0000116 bool hasV7Ops() const {
117 return STI.getFeatureBits() & ARM::HasV7Ops;
118 }
Evan Cheng32869202011-07-08 22:36:29 +0000119 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000120 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
121 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000122 }
James Molloyacad68d2011-09-28 14:21:38 +0000123 bool isMClass() const {
124 return STI.getFeatureBits() & ARM::FeatureMClass;
125 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000126
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000127 /// @name Auto-generated Match Functions
128 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000129
Chris Lattner0692ee62010-09-06 19:11:01 +0000130#define GET_ASSEMBLER_HEADER
131#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000132
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133 /// }
134
Jim Grosbach89df9962011-08-26 21:43:41 +0000135 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000136 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000137 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000140 OperandMatchResultTy parseCoprocOptionOperand(
141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000142 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000148 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
149 StringRef Op, int Low, int High);
150 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
151 return parsePKHImm(O, "lsl", 0, 31);
152 }
153 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "asr", 1, 32);
155 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000156 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000157 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000158 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000159 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000160 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000161 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000162 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000163 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000200 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000204 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000208
209 bool validateInstruction(MCInst &Inst,
210 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000211 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000212 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000213 bool shouldOmitCCOutOperand(StringRef Mnemonic,
214 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000215
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000216public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000217 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000218 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000219 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000220 Match_RequiresV6,
221 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000222 };
223
Evan Chengffc0e732011-07-09 05:47:46 +0000224 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000225 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000226 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000227
Evan Chengebdeeab2011-07-08 01:53:10 +0000228 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230
231 // Not in an ITBlock to start with.
232 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000233 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 // Implementation of the MCTargetAsmParser interface:
236 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
237 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000238 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 bool ParseDirective(AsmToken DirectiveID);
240
Jim Grosbach47a0d522011-08-16 20:45:50 +0000241 unsigned checkTargetMatchPredicate(MCInst &Inst);
242
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool MatchAndEmitInstruction(SMLoc IDLoc,
244 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
245 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000246};
Jim Grosbach16c74252010-10-29 14:46:02 +0000247} // end anonymous namespace
248
Chris Lattner3a697562010-10-28 17:20:03 +0000249namespace {
250
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000251/// ARMOperand - Instances of this class represent a parsed ARM machine
252/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000253class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000254 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000255 k_CondCode,
256 k_CCOut,
257 k_ITCondMask,
258 k_CoprocNum,
259 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000260 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000261 k_Immediate,
262 k_FPImmediate,
263 k_MemBarrierOpt,
264 k_Memory,
265 k_PostIndexRegister,
266 k_MSRMask,
267 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000268 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000269 k_Register,
270 k_RegisterList,
271 k_DPRRegisterList,
272 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000273 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000274 k_ShiftedRegister,
275 k_ShiftedImmediate,
276 k_ShifterImmediate,
277 k_RotateImmediate,
278 k_BitfieldDescriptor,
279 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000280 } Kind;
281
Sean Callanan76264762010-04-02 22:27:05 +0000282 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000283 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000284
285 union {
286 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000287 ARMCC::CondCodes Val;
288 } CC;
289
290 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000291 unsigned Val;
292 } Cop;
293
294 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000295 unsigned Val;
296 } CoprocOption;
297
298 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000299 unsigned Mask:4;
300 } ITMask;
301
302 struct {
303 ARM_MB::MemBOpt Val;
304 } MBOpt;
305
306 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000307 ARM_PROC::IFlags Val;
308 } IFlags;
309
310 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000311 unsigned Val;
312 } MMask;
313
314 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000315 const char *Data;
316 unsigned Length;
317 } Tok;
318
319 struct {
320 unsigned RegNum;
321 } Reg;
322
Jim Grosbach862019c2011-10-18 23:02:30 +0000323 // A vector register list is a sequential list of 1 to 4 registers.
324 struct {
325 unsigned RegNum;
326 unsigned Count;
327 } VectorList;
328
Bill Wendling8155e5b2010-11-06 22:19:43 +0000329 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000330 unsigned Val;
331 } VectorIndex;
332
333 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000334 const MCExpr *Val;
335 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000336
Jim Grosbach9d390362011-10-03 23:38:36 +0000337 struct {
338 unsigned Val; // encoded 8-bit representation
339 } FPImm;
340
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000341 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000342 struct {
343 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000344 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
345 // was specified.
346 const MCConstantExpr *OffsetImm; // Offset immediate value
347 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
348 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000349 unsigned ShiftImm; // shift for OffsetReg.
350 unsigned Alignment; // 0 = no alignment specified
351 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000352 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000353 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000354
355 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000356 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000357 bool isAdd;
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000360 } PostIdxReg;
361
362 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000363 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000364 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000365 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000366 struct {
367 ARM_AM::ShiftOpc ShiftTy;
368 unsigned SrcReg;
369 unsigned ShiftReg;
370 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000371 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000376 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000377 struct {
378 unsigned Imm;
379 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000380 struct {
381 unsigned LSB;
382 unsigned Width;
383 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000384 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000385
Bill Wendling146018f2010-11-06 21:42:12 +0000386 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
387public:
Sean Callanan76264762010-04-02 22:27:05 +0000388 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
389 Kind = o.Kind;
390 StartLoc = o.StartLoc;
391 EndLoc = o.EndLoc;
392 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000394 CC = o.CC;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000397 ITMask = o.ITMask;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000400 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_CCOut:
403 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Reg = o.Reg;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_RegisterList:
407 case k_DPRRegisterList:
408 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000409 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000410 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000411 case k_VectorList:
412 VectorList = o.VectorList;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_CoprocNum:
415 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000416 Cop = o.Cop;
417 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000418 case k_CoprocOption:
419 CoprocOption = o.CoprocOption;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000422 Imm = o.Imm;
423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000425 FPImm = o.FPImm;
426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000428 MBOpt = o.MBOpt;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000431 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000434 PostIdxReg = o.PostIdxReg;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000437 MMask = o.MMask;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000440 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000443 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000446 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000449 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000452 RotImm = o.RotImm;
453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000455 Bitfield = o.Bitfield;
456 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
Sean Callanan76264762010-04-02 22:27:05 +0000460 }
461 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000462
Sean Callanan76264762010-04-02 22:27:05 +0000463 /// getStartLoc - Get the location of the first token of this operand.
464 SMLoc getStartLoc() const { return StartLoc; }
465 /// getEndLoc - Get the location of the last token of this operand.
466 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000467
Daniel Dunbar8462b302010-08-11 06:36:53 +0000468 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000469 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000470 return CC.Val;
471 }
472
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000473 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000474 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000475 return Cop.Val;
476 }
477
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000478 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000479 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000480 return StringRef(Tok.Data, Tok.Length);
481 }
482
483 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000484 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000485 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 }
487
Bill Wendling5fa22a12010-11-09 23:28:44 +0000488 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000489 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
490 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000491 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000492 }
493
Kevin Enderbycfe07242009-10-13 22:19:02 +0000494 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000495 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000496 return Imm.Val;
497 }
498
Jim Grosbach9d390362011-10-03 23:38:36 +0000499 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000501 return FPImm.Val;
502 }
503
Jim Grosbach460a9052011-10-07 23:56:00 +0000504 unsigned getVectorIndex() const {
505 assert(Kind == k_VectorIndex && "Invalid access!");
506 return VectorIndex.Val;
507 }
508
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000509 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000510 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000511 return MBOpt.Val;
512 }
513
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000514 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000515 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000516 return IFlags.Val;
517 }
518
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000519 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000520 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000521 return MMask.Val;
522 }
523
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 bool isCoprocNum() const { return Kind == k_CoprocNum; }
525 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000526 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 bool isCondCode() const { return Kind == k_CondCode; }
528 bool isCCOut() const { return Kind == k_CCOut; }
529 bool isITMask() const { return Kind == k_ITCondMask; }
530 bool isITCondCode() const { return Kind == k_CondCode; }
531 bool isImm() const { return Kind == k_Immediate; }
532 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000533 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000535 return false;
536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
537 if (!CE) return false;
538 int64_t Value = CE->getValue();
539 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
540 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000541 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
548 }
549 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
556 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000557 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value < 256;
564 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000565 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 8;
572 }
573 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000574 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000575 return false;
576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
577 if (!CE) return false;
578 int64_t Value = CE->getValue();
579 return Value >= 0 && Value < 16;
580 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000581 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000583 return false;
584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 32;
588 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000589 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000591 return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = CE->getValue();
595 return Value > 0 && Value < 17;
596 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000597 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000599 return false;
600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value > 0 && Value < 33;
604 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000605 bool isImm0_32() const {
606 if (Kind != k_Immediate)
607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 33;
612 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000613 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value >= 0 && Value < 65536;
620 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000621 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 // If it's not a constant expression, it'll generate a fixup and be
626 // handled later.
627 if (!CE) return true;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 65536;
630 }
Jim Grosbached838482011-07-26 16:24:27 +0000631 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000633 return false;
634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
635 if (!CE) return false;
636 int64_t Value = CE->getValue();
637 return Value >= 0 && Value <= 0xffffff;
638 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000639 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000641 return false;
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value > 0 && Value < 33;
646 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000647 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000649 return false;
650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value >= 0 && Value < 32;
654 }
655 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return Value > 0 && Value <= 32;
662 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000663 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return ARM_AM::getSOImmVal(Value) != -1;
670 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000671 bool isARMSOImmNot() const {
672 if (Kind != k_Immediate)
673 return false;
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
675 if (!CE) return false;
676 int64_t Value = CE->getValue();
677 return ARM_AM::getSOImmVal(~Value) != -1;
678 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000679 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000680 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000681 return false;
682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return ARM_AM::getT2SOImmVal(Value) != -1;
686 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000687 bool isT2SOImmNot() const {
688 if (Kind != k_Immediate)
689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return ARM_AM::getT2SOImmVal(~Value) != -1;
694 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000695 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000696 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value == 1 || Value == 0;
702 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000703 bool isReg() const { return Kind == k_Register; }
704 bool isRegList() const { return Kind == k_RegisterList; }
705 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
706 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
707 bool isToken() const { return Kind == k_Token; }
708 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
709 bool isMemory() const { return Kind == k_Memory; }
710 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
711 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
712 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
713 bool isRotImm() const { return Kind == k_RotateImmediate; }
714 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
715 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000716 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000717 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000718 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000719 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000720 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000721 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000722 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000723 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
724 (alignOK || Memory.Alignment == 0);
725 }
726 bool isAlignedMemory() const {
727 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000728 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000729 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000730 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000731 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000732 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000733 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000734 if (!Memory.OffsetImm) return true;
735 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000736 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000737 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000738 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000739 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000740 return false;
741 // Immediate offset in range [-4095, 4095].
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 int64_t Val = CE->getValue();
745 return Val > -4096 && Val < 4096;
746 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000747 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000748 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000749 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000751 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000752 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000753 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000754 if (!Memory.OffsetImm) return true;
755 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000756 return Val > -256 && Val < 256;
757 }
758 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000760 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000762 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
763 // Immediate offset in range [-255, 255].
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000767 // Special case, #-0 is INT32_MIN.
768 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000769 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000770 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000771 // If we have an immediate that's not a constant, treat it as a label
772 // reference needing a fixup. If it is a constant, it's something else
773 // and we reject it.
774 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
775 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000776 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000777 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000778 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000779 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000780 if (!Memory.OffsetImm) return true;
781 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000782 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000783 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000784 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000785 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
791 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
794 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000795 return false;
796 return true;
797 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000798 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000799 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000800 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000801 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000802 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000803 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
805 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000806 return false;
807 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000809 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000811 return false;
812 return true;
813 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000814 bool isMemThumbRR() const {
815 // Thumb reg+reg addressing is simple. Just two registers, a base and
816 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000817 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000819 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000820 return isARMLowRegister(Memory.BaseRegNum) &&
821 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000822 }
823 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000825 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000826 return false;
827 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000828 if (!Memory.OffsetImm) return true;
829 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000830 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
831 }
Jim Grosbach38466302011-08-19 18:55:51 +0000832 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000833 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000835 return false;
836 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000839 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
840 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000841 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000842 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000843 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000844 return false;
845 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000846 if (!Memory.OffsetImm) return true;
847 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000848 return Val >= 0 && Val <= 31;
849 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000850 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000851 if (!isMemory() || Memory.OffsetRegNum != 0 ||
852 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000853 return false;
854 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000857 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000858 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000859 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000865 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000867 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000873 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000877 return false;
878 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000881 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000883 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000885 return false;
886 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000889 return Val >= 0 && Val < 256;
890 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000891 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000893 return false;
894 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000897 return Val > -256 && Val < 0;
898 }
899 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000900 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000901 return false;
902 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000905 return (Val >= 0 && Val < 4096);
906 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000908 // If we have an immediate that's not a constant, treat it as a label
909 // reference needing a fixup. If it is a constant, it's something else
910 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000911 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000912 return true;
913
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000915 return false;
916 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000919 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000920 }
921 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000927 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000929 bool isPostIdxImm8s4() const {
930 if (Kind != k_Immediate)
931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
935 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
936 (Val == INT32_MIN);
937 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000938
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000939 bool isMSRMask() const { return Kind == k_MSRMask; }
940 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000941
Jim Grosbach0e387b22011-10-17 22:26:03 +0000942 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000943 bool isVecListOneD() const {
944 if (Kind != k_VectorList) return false;
945 return VectorList.Count == 1;
946 }
947
Jim Grosbach280dfad2011-10-21 18:54:25 +0000948 bool isVecListTwoD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 2;
951 }
952
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000953 bool isVecListThreeD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 3;
956 }
957
Jim Grosbachb6310312011-10-21 20:35:01 +0000958 bool isVecListFourD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 4;
961 }
962
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000963 bool isVecListTwoQ() const {
964 if (Kind != k_VectorList) return false;
965 //FIXME: We haven't taught the parser to handle by-two register lists
966 // yet, so don't pretend to know one.
967 return VectorList.Count == 2 && false;
968 }
969
Jim Grosbach460a9052011-10-07 23:56:00 +0000970 bool isVectorIndex8() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 8;
973 }
974 bool isVectorIndex16() const {
975 if (Kind != k_VectorIndex) return false;
976 return VectorIndex.Val < 4;
977 }
978 bool isVectorIndex32() const {
979 if (Kind != k_VectorIndex) return false;
980 return VectorIndex.Val < 2;
981 }
982
Jim Grosbach0e387b22011-10-17 22:26:03 +0000983 bool isNEONi8splat() const {
984 if (Kind != k_Immediate)
985 return false;
986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
987 // Must be a constant.
988 if (!CE) return false;
989 int64_t Value = CE->getValue();
990 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
991 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000992 return Value >= 0 && Value < 256;
993 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000994
Jim Grosbachea461102011-10-17 23:09:09 +0000995 bool isNEONi16splat() const {
996 if (Kind != k_Immediate)
997 return false;
998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
999 // Must be a constant.
1000 if (!CE) return false;
1001 int64_t Value = CE->getValue();
1002 // i16 value in the range [0,255] or [0x0100, 0xff00]
1003 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1004 }
1005
Jim Grosbach6248a542011-10-18 00:22:00 +00001006 bool isNEONi32splat() const {
1007 if (Kind != k_Immediate)
1008 return false;
1009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1010 // Must be a constant.
1011 if (!CE) return false;
1012 int64_t Value = CE->getValue();
1013 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1014 return (Value >= 0 && Value < 256) ||
1015 (Value >= 0x0100 && Value <= 0xff00) ||
1016 (Value >= 0x010000 && Value <= 0xff0000) ||
1017 (Value >= 0x01000000 && Value <= 0xff000000);
1018 }
1019
1020 bool isNEONi32vmov() const {
1021 if (Kind != k_Immediate)
1022 return false;
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 // Must be a constant.
1025 if (!CE) return false;
1026 int64_t Value = CE->getValue();
1027 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1028 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000) ||
1033 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1034 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1035 }
1036
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001037 bool isNEONi64splat() const {
1038 if (Kind != k_Immediate)
1039 return false;
1040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 // Must be a constant.
1042 if (!CE) return false;
1043 uint64_t Value = CE->getValue();
1044 // i64 value with each byte being either 0 or 0xff.
1045 for (unsigned i = 0; i < 8; ++i)
1046 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1047 return true;
1048 }
1049
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001050 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001051 // Add as immediates when possible. Null MCExpr = 0.
1052 if (Expr == 0)
1053 Inst.addOperand(MCOperand::CreateImm(0));
1054 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001055 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1056 else
1057 Inst.addOperand(MCOperand::CreateExpr(Expr));
1058 }
1059
Daniel Dunbar8462b302010-08-11 06:36:53 +00001060 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001061 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001062 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001063 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1064 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001065 }
1066
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001067 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1070 }
1071
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001072 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1075 }
1076
1077 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1080 }
1081
Jim Grosbach89df9962011-08-26 21:43:41 +00001082 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1085 }
1086
1087 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1090 }
1091
Jim Grosbachd67641b2010-12-06 18:21:12 +00001092 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateReg(getReg()));
1095 }
1096
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001097 void addRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateReg(getReg()));
1100 }
1101
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001102 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001103 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001104 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1105 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001107 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001108 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001109 }
1110
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001111 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001112 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001113 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1114 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001115 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001116 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001117 }
1118
Jim Grosbach580f4a92011-07-25 22:20:28 +00001119 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001120 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001121 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1122 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001123 }
1124
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001125 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001126 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001127 const SmallVectorImpl<unsigned> &RegList = getRegList();
1128 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001129 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1130 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001131 }
1132
Bill Wendling0f630752010-11-17 04:32:08 +00001133 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1134 addRegListOperands(Inst, N);
1135 }
1136
1137 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1138 addRegListOperands(Inst, N);
1139 }
1140
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001141 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1142 assert(N == 1 && "Invalid number of operands!");
1143 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1144 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1145 }
1146
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001147 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 // Munge the lsb/width into a bitfield mask.
1150 unsigned lsb = Bitfield.LSB;
1151 unsigned width = Bitfield.Width;
1152 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1153 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1154 (32 - (lsb + width)));
1155 Inst.addOperand(MCOperand::CreateImm(Mask));
1156 }
1157
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001158 void addImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 addExpr(Inst, getImm());
1161 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001162
Jim Grosbach9d390362011-10-03 23:38:36 +00001163 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
1165 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1166 }
1167
Jim Grosbacha77295d2011-09-08 22:07:06 +00001168 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // FIXME: We really want to scale the value here, but the LDRD/STRD
1171 // instruction don't encode operands that way yet.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1174 }
1175
Jim Grosbach72f39f82011-08-24 21:22:15 +00001176 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 // The immediate is scaled by four in the encoding and is stored
1179 // in the MCInst as such. Lop off the low two bits here.
1180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1181 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1182 }
1183
1184 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 // The immediate is scaled by four in the encoding and is stored
1187 // in the MCInst as such. Lop off the low two bits here.
1188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1189 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1190 }
1191
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001192 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 addExpr(Inst, getImm());
1195 }
1196
Jim Grosbach83ab0702011-07-13 22:01:08 +00001197 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1198 assert(N == 1 && "Invalid number of operands!");
1199 addExpr(Inst, getImm());
1200 }
1201
1202 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
1204 addExpr(Inst, getImm());
1205 }
1206
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001207 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1208 assert(N == 1 && "Invalid number of operands!");
1209 addExpr(Inst, getImm());
1210 }
1211
Jim Grosbachf4943352011-07-25 23:09:14 +00001212 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 // The constant encodes as the immediate-1, and we store in the instruction
1215 // the bits as encoded, so subtract off one here.
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1218 }
1219
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001220 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 // The constant encodes as the immediate-1, and we store in the instruction
1223 // the bits as encoded, so subtract off one here.
1224 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1225 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1226 }
1227
Jim Grosbachee10ff82011-11-10 19:18:01 +00001228 void addImm0_32Operands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 addExpr(Inst, getImm());
1231 }
1232
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001233 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 addExpr(Inst, getImm());
1236 }
1237
Jim Grosbachffa32252011-07-19 19:13:28 +00001238 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
1240 addExpr(Inst, getImm());
1241 }
1242
Jim Grosbached838482011-07-26 16:24:27 +00001243 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 addExpr(Inst, getImm());
1246 }
1247
Jim Grosbach70939ee2011-08-17 21:51:27 +00001248 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1249 assert(N == 1 && "Invalid number of operands!");
1250 // The constant encodes as the immediate, except for 32, which encodes as
1251 // zero.
1252 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1253 unsigned Imm = CE->getValue();
1254 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1255 }
1256
Jim Grosbachf6c05252011-07-21 17:23:04 +00001257 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
1259 addExpr(Inst, getImm());
1260 }
1261
1262 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1263 assert(N == 1 && "Invalid number of operands!");
1264 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1265 // the instruction as well.
1266 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1267 int Val = CE->getValue();
1268 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1269 }
1270
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001271 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 addExpr(Inst, getImm());
1274 }
1275
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001276 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 addExpr(Inst, getImm());
1279 }
1280
Jim Grosbach89a63372011-10-28 22:36:30 +00001281 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 // The operand is actually a t2_so_imm, but we have its bitwise
1284 // negation in the assembly source, so twiddle it here.
1285 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1286 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1287 }
1288
Jim Grosbache70ec842011-10-28 22:50:54 +00001289 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
1291 // The operand is actually a so_imm, but we have its bitwise
1292 // negation in the assembly source, so twiddle it here.
1293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1294 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1295 }
1296
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001297 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 addExpr(Inst, getImm());
1300 }
1301
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001302 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
1304 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1305 }
1306
Jim Grosbach7ce05792011-08-03 23:50:40 +00001307 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001309 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001310 }
1311
Jim Grosbach57dcb852011-10-11 17:29:55 +00001312 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1313 assert(N == 2 && "Invalid number of operands!");
1314 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1315 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1316 }
1317
Jim Grosbach7ce05792011-08-03 23:50:40 +00001318 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1319 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001320 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1321 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001322 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1323 // Special case for #-0
1324 if (Val == INT32_MIN) Val = 0;
1325 if (Val < 0) Val = -Val;
1326 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1327 } else {
1328 // For register offset, we encode the shift type and negation flag
1329 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001330 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1331 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001332 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001333 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1334 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001335 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001336 }
1337
Jim Grosbach039c2e12011-08-04 23:01:30 +00001338 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 2 && "Invalid number of operands!");
1340 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1341 assert(CE && "non-constant AM2OffsetImm operand!");
1342 int32_t Val = CE->getValue();
1343 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1344 // Special case for #-0
1345 if (Val == INT32_MIN) Val = 0;
1346 if (Val < 0) Val = -Val;
1347 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1348 Inst.addOperand(MCOperand::CreateReg(0));
1349 Inst.addOperand(MCOperand::CreateImm(Val));
1350 }
1351
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001352 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001354 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1355 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001356 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1357 // Special case for #-0
1358 if (Val == INT32_MIN) Val = 0;
1359 if (Val < 0) Val = -Val;
1360 Val = ARM_AM::getAM3Opc(AddSub, Val);
1361 } else {
1362 // For register offset, we encode the shift type and negation flag
1363 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001364 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001365 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1367 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001368 Inst.addOperand(MCOperand::CreateImm(Val));
1369 }
1370
1371 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1372 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001373 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001374 int32_t Val =
1375 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1376 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1377 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001378 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001379 }
1380
1381 // Constant offset.
1382 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1383 int32_t Val = CE->getValue();
1384 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1385 // Special case for #-0
1386 if (Val == INT32_MIN) Val = 0;
1387 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001388 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001389 Inst.addOperand(MCOperand::CreateReg(0));
1390 Inst.addOperand(MCOperand::CreateImm(Val));
1391 }
1392
Jim Grosbach7ce05792011-08-03 23:50:40 +00001393 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001395 // If we have an immediate that's not a constant, treat it as a label
1396 // reference needing a fixup. If it is a constant, it's something else
1397 // and we reject it.
1398 if (isImm()) {
1399 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1400 Inst.addOperand(MCOperand::CreateImm(0));
1401 return;
1402 }
1403
Jim Grosbach7ce05792011-08-03 23:50:40 +00001404 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001405 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001406 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1407 // Special case for #-0
1408 if (Val == INT32_MIN) Val = 0;
1409 if (Val < 0) Val = -Val;
1410 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001412 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001413 }
1414
Jim Grosbacha77295d2011-09-08 22:07:06 +00001415 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001417 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1418 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001419 Inst.addOperand(MCOperand::CreateImm(Val));
1420 }
1421
Jim Grosbachb6aed502011-09-09 18:37:27 +00001422 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1423 assert(N == 2 && "Invalid number of operands!");
1424 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001425 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1426 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001427 Inst.addOperand(MCOperand::CreateImm(Val));
1428 }
1429
Jim Grosbach7ce05792011-08-03 23:50:40 +00001430 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001432 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1433 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001434 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001435 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001436
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001437 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1438 addMemImm8OffsetOperands(Inst, N);
1439 }
1440
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001441 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001442 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001443 }
1444
1445 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
1447 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001448 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001449 addExpr(Inst, getImm());
1450 Inst.addOperand(MCOperand::CreateImm(0));
1451 return;
1452 }
1453
1454 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001455 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001457 Inst.addOperand(MCOperand::CreateImm(Val));
1458 }
1459
Jim Grosbach7ce05792011-08-03 23:50:40 +00001460 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001462 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001463 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001464 addExpr(Inst, getImm());
1465 Inst.addOperand(MCOperand::CreateImm(0));
1466 return;
1467 }
1468
1469 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001470 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1471 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001472 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001473 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001474
Jim Grosbach7f739be2011-09-19 22:21:13 +00001475 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001477 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1478 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001479 }
1480
1481 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1482 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001483 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1484 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001485 }
1486
Jim Grosbach7ce05792011-08-03 23:50:40 +00001487 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001489 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1490 Memory.ShiftImm, Memory.ShiftType);
1491 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1492 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001493 Inst.addOperand(MCOperand::CreateImm(Val));
1494 }
1495
Jim Grosbachab899c12011-09-07 23:10:15 +00001496 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001498 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1499 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1500 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001501 }
1502
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001505 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1506 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001507 }
1508
Jim Grosbach60f91a32011-08-19 17:55:24 +00001509 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1510 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001511 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1512 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001513 Inst.addOperand(MCOperand::CreateImm(Val));
1514 }
1515
Jim Grosbach38466302011-08-19 18:55:51 +00001516 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001518 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1519 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001520 Inst.addOperand(MCOperand::CreateImm(Val));
1521 }
1522
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001523 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001525 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1526 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001527 Inst.addOperand(MCOperand::CreateImm(Val));
1528 }
1529
Jim Grosbachecd85892011-08-19 18:13:48 +00001530 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001532 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1533 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001534 Inst.addOperand(MCOperand::CreateImm(Val));
1535 }
1536
Jim Grosbach7ce05792011-08-03 23:50:40 +00001537 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1540 assert(CE && "non-constant post-idx-imm8 operand!");
1541 int Imm = CE->getValue();
1542 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001543 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001544 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1545 Inst.addOperand(MCOperand::CreateImm(Imm));
1546 }
1547
Jim Grosbach2bd01182011-10-11 21:55:36 +00001548 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1551 assert(CE && "non-constant post-idx-imm8s4 operand!");
1552 int Imm = CE->getValue();
1553 bool isAdd = Imm >= 0;
1554 if (Imm == INT32_MIN) Imm = 0;
1555 // Immediate is scaled by 4.
1556 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1557 Inst.addOperand(MCOperand::CreateImm(Imm));
1558 }
1559
Jim Grosbach7ce05792011-08-03 23:50:40 +00001560 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 2 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001563 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1564 }
1565
1566 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
1568 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1569 // The sign, shift type, and shift amount are encoded in a single operand
1570 // using the AM2 encoding helpers.
1571 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1572 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1573 PostIdxReg.ShiftTy);
1574 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001575 }
1576
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001577 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1580 }
1581
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001582 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1585 }
1586
Jim Grosbach862019c2011-10-18 23:02:30 +00001587 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1590 }
1591
Jim Grosbach280dfad2011-10-21 18:54:25 +00001592 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 // Only the first register actually goes on the instruction. The rest
1595 // are implied by the opcode.
1596 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1597 }
1598
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001599 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 // Only the first register actually goes on the instruction. The rest
1602 // are implied by the opcode.
1603 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1604 }
1605
Jim Grosbachb6310312011-10-21 20:35:01 +00001606 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
1608 // Only the first register actually goes on the instruction. The rest
1609 // are implied by the opcode.
1610 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1611 }
1612
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001613 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // Only the first register actually goes on the instruction. The rest
1616 // are implied by the opcode.
1617 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1618 }
1619
Jim Grosbach460a9052011-10-07 23:56:00 +00001620 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1621 assert(N == 1 && "Invalid number of operands!");
1622 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1623 }
1624
1625 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1626 assert(N == 1 && "Invalid number of operands!");
1627 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1628 }
1629
1630 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1631 assert(N == 1 && "Invalid number of operands!");
1632 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1633 }
1634
Jim Grosbach0e387b22011-10-17 22:26:03 +00001635 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1636 assert(N == 1 && "Invalid number of operands!");
1637 // The immediate encodes the type of constant as well as the value.
1638 // Mask in that this is an i8 splat.
1639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1640 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1641 }
1642
Jim Grosbachea461102011-10-17 23:09:09 +00001643 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1644 assert(N == 1 && "Invalid number of operands!");
1645 // The immediate encodes the type of constant as well as the value.
1646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1647 unsigned Value = CE->getValue();
1648 if (Value >= 256)
1649 Value = (Value >> 8) | 0xa00;
1650 else
1651 Value |= 0x800;
1652 Inst.addOperand(MCOperand::CreateImm(Value));
1653 }
1654
Jim Grosbach6248a542011-10-18 00:22:00 +00001655 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1656 assert(N == 1 && "Invalid number of operands!");
1657 // The immediate encodes the type of constant as well as the value.
1658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1659 unsigned Value = CE->getValue();
1660 if (Value >= 256 && Value <= 0xff00)
1661 Value = (Value >> 8) | 0x200;
1662 else if (Value > 0xffff && Value <= 0xff0000)
1663 Value = (Value >> 16) | 0x400;
1664 else if (Value > 0xffffff)
1665 Value = (Value >> 24) | 0x600;
1666 Inst.addOperand(MCOperand::CreateImm(Value));
1667 }
1668
1669 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1670 assert(N == 1 && "Invalid number of operands!");
1671 // The immediate encodes the type of constant as well as the value.
1672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1673 unsigned Value = CE->getValue();
1674 if (Value >= 256 && Value <= 0xffff)
1675 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1676 else if (Value > 0xffff && Value <= 0xffffff)
1677 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1678 else if (Value > 0xffffff)
1679 Value = (Value >> 24) | 0x600;
1680 Inst.addOperand(MCOperand::CreateImm(Value));
1681 }
1682
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001683 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1684 assert(N == 1 && "Invalid number of operands!");
1685 // The immediate encodes the type of constant as well as the value.
1686 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1687 uint64_t Value = CE->getValue();
1688 unsigned Imm = 0;
1689 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1690 Imm |= (Value & 1) << i;
1691 }
1692 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1693 }
1694
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001695 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001696
Jim Grosbach89df9962011-08-26 21:43:41 +00001697 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001698 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001699 Op->ITMask.Mask = Mask;
1700 Op->StartLoc = S;
1701 Op->EndLoc = S;
1702 return Op;
1703 }
1704
Chris Lattner3a697562010-10-28 17:20:03 +00001705 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001706 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001707 Op->CC.Val = CC;
1708 Op->StartLoc = S;
1709 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001710 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001711 }
1712
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001713 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001714 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001715 Op->Cop.Val = CopVal;
1716 Op->StartLoc = S;
1717 Op->EndLoc = S;
1718 return Op;
1719 }
1720
1721 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001722 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001723 Op->Cop.Val = CopVal;
1724 Op->StartLoc = S;
1725 Op->EndLoc = S;
1726 return Op;
1727 }
1728
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001729 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1730 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1731 Op->Cop.Val = Val;
1732 Op->StartLoc = S;
1733 Op->EndLoc = E;
1734 return Op;
1735 }
1736
Jim Grosbachd67641b2010-12-06 18:21:12 +00001737 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001738 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001739 Op->Reg.RegNum = RegNum;
1740 Op->StartLoc = S;
1741 Op->EndLoc = S;
1742 return Op;
1743 }
1744
Chris Lattner3a697562010-10-28 17:20:03 +00001745 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001747 Op->Tok.Data = Str.data();
1748 Op->Tok.Length = Str.size();
1749 Op->StartLoc = S;
1750 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001751 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001752 }
1753
Bill Wendling50d0f582010-11-18 23:43:05 +00001754 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001756 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001757 Op->StartLoc = S;
1758 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001759 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001760 }
1761
Jim Grosbache8606dc2011-07-13 17:50:29 +00001762 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1763 unsigned SrcReg,
1764 unsigned ShiftReg,
1765 unsigned ShiftImm,
1766 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001767 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001768 Op->RegShiftedReg.ShiftTy = ShTy;
1769 Op->RegShiftedReg.SrcReg = SrcReg;
1770 Op->RegShiftedReg.ShiftReg = ShiftReg;
1771 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001772 Op->StartLoc = S;
1773 Op->EndLoc = E;
1774 return Op;
1775 }
1776
Owen Anderson92a20222011-07-21 18:54:16 +00001777 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1778 unsigned SrcReg,
1779 unsigned ShiftImm,
1780 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001781 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001782 Op->RegShiftedImm.ShiftTy = ShTy;
1783 Op->RegShiftedImm.SrcReg = SrcReg;
1784 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001785 Op->StartLoc = S;
1786 Op->EndLoc = E;
1787 return Op;
1788 }
1789
Jim Grosbach580f4a92011-07-25 22:20:28 +00001790 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001791 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001792 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001793 Op->ShifterImm.isASR = isASR;
1794 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001795 Op->StartLoc = S;
1796 Op->EndLoc = E;
1797 return Op;
1798 }
1799
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001800 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001801 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001802 Op->RotImm.Imm = Imm;
1803 Op->StartLoc = S;
1804 Op->EndLoc = E;
1805 return Op;
1806 }
1807
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001808 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1809 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001811 Op->Bitfield.LSB = LSB;
1812 Op->Bitfield.Width = Width;
1813 Op->StartLoc = S;
1814 Op->EndLoc = E;
1815 return Op;
1816 }
1817
Bill Wendling7729e062010-11-09 22:44:22 +00001818 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001819 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001820 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001821 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001822
Jim Grosbachd300b942011-09-13 22:56:44 +00001823 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001824 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001825 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001826 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001827 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001828
1829 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001830 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001831 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001832 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001833 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001834 Op->StartLoc = StartLoc;
1835 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001836 return Op;
1837 }
1838
Jim Grosbach862019c2011-10-18 23:02:30 +00001839 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1840 SMLoc S, SMLoc E) {
1841 ARMOperand *Op = new ARMOperand(k_VectorList);
1842 Op->VectorList.RegNum = RegNum;
1843 Op->VectorList.Count = Count;
1844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
1848
Jim Grosbach460a9052011-10-07 23:56:00 +00001849 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1850 MCContext &Ctx) {
1851 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1852 Op->VectorIndex.Val = Idx;
1853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
Chris Lattner3a697562010-10-28 17:20:03 +00001858 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001859 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001860 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001861 Op->StartLoc = S;
1862 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001863 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001864 }
1865
Jim Grosbach9d390362011-10-03 23:38:36 +00001866 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001867 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001868 Op->FPImm.Val = Val;
1869 Op->StartLoc = S;
1870 Op->EndLoc = S;
1871 return Op;
1872 }
1873
Jim Grosbach7ce05792011-08-03 23:50:40 +00001874 static ARMOperand *CreateMem(unsigned BaseRegNum,
1875 const MCConstantExpr *OffsetImm,
1876 unsigned OffsetRegNum,
1877 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001878 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001879 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001880 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001881 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001882 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001883 Op->Memory.BaseRegNum = BaseRegNum;
1884 Op->Memory.OffsetImm = OffsetImm;
1885 Op->Memory.OffsetRegNum = OffsetRegNum;
1886 Op->Memory.ShiftType = ShiftType;
1887 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001888 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001889 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001890 Op->StartLoc = S;
1891 Op->EndLoc = E;
1892 return Op;
1893 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001894
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001895 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1896 ARM_AM::ShiftOpc ShiftTy,
1897 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001898 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001900 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001901 Op->PostIdxReg.isAdd = isAdd;
1902 Op->PostIdxReg.ShiftTy = ShiftTy;
1903 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001904 Op->StartLoc = S;
1905 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001906 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001907 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001908
1909 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001911 Op->MBOpt.Val = Opt;
1912 Op->StartLoc = S;
1913 Op->EndLoc = S;
1914 return Op;
1915 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001916
1917 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001919 Op->IFlags.Val = IFlags;
1920 Op->StartLoc = S;
1921 Op->EndLoc = S;
1922 return Op;
1923 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001924
1925 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001927 Op->MMask.Val = MMask;
1928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001932};
1933
1934} // end anonymous namespace.
1935
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001936void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001937 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001938 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001939 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1940 << ") >";
1941 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001943 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001944 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001945 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001946 OS << "<ccout " << getReg() << ">";
1947 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001948 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001949 static const char *MaskStr[] = {
1950 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1951 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1952 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001953 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1954 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1955 break;
1956 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001957 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001958 OS << "<coprocessor number: " << getCoproc() << ">";
1959 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001961 OS << "<coprocessor register: " << getCoproc() << ">";
1962 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001963 case k_CoprocOption:
1964 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1965 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001967 OS << "<mask: " << getMSRMask() << ">";
1968 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001970 getImm()->print(OS);
1971 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001972 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001973 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1974 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001975 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001976 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001977 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001978 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001979 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001980 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001981 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1982 << PostIdxReg.RegNum;
1983 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1984 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1985 << PostIdxReg.ShiftImm;
1986 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001987 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001989 OS << "<ARM_PROC::";
1990 unsigned IFlags = getProcIFlags();
1991 for (int i=2; i >= 0; --i)
1992 if (IFlags & (1 << i))
1993 OS << ARM_PROC::IFlagsToString(1 << i);
1994 OS << ">";
1995 break;
1996 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001997 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001998 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001999 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002001 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2002 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002003 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002004 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002005 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002006 << RegShiftedReg.SrcReg
2007 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
2008 << ", " << RegShiftedReg.ShiftReg << ", "
2009 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00002010 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002011 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002012 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002013 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002014 << RegShiftedImm.SrcReg
2015 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
2016 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00002017 << ">";
2018 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002019 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002020 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2021 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002022 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002023 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2024 << ", width: " << Bitfield.Width << ">";
2025 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002026 case k_RegisterList:
2027 case k_DPRRegisterList:
2028 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002029 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002030
Bill Wendling5fa22a12010-11-09 23:28:44 +00002031 const SmallVectorImpl<unsigned> &RegList = getRegList();
2032 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002033 I = RegList.begin(), E = RegList.end(); I != E; ) {
2034 OS << *I;
2035 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002036 }
2037
2038 OS << ">";
2039 break;
2040 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002041 case k_VectorList:
2042 OS << "<vector_list " << VectorList.Count << " * "
2043 << VectorList.RegNum << ">";
2044 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002046 OS << "'" << getToken() << "'";
2047 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002048 case k_VectorIndex:
2049 OS << "<vectorindex " << getVectorIndex() << ">";
2050 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002051 }
2052}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002053
2054/// @name Auto-generated Match Functions
2055/// {
2056
2057static unsigned MatchRegisterName(StringRef Name);
2058
2059/// }
2060
Bob Wilson69df7232011-02-03 21:46:10 +00002061bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2062 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002063 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002064
2065 return (RegNo == (unsigned)-1);
2066}
2067
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002068/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002069/// and if it is a register name the token is eaten and the register number is
2070/// returned. Otherwise return -1.
2071///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002072int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002073 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002074 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002075
Chris Lattnere5658fa2010-10-30 04:09:10 +00002076 // FIXME: Validate register for the current architecture; we have to do
2077 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002078 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002079 unsigned RegNum = MatchRegisterName(lowerCase);
2080 if (!RegNum) {
2081 RegNum = StringSwitch<unsigned>(lowerCase)
2082 .Case("r13", ARM::SP)
2083 .Case("r14", ARM::LR)
2084 .Case("r15", ARM::PC)
2085 .Case("ip", ARM::R12)
2086 .Default(0);
2087 }
2088 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002089
Chris Lattnere5658fa2010-10-30 04:09:10 +00002090 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002091
Chris Lattnere5658fa2010-10-30 04:09:10 +00002092 return RegNum;
2093}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002094
Jim Grosbach19906722011-07-13 18:49:30 +00002095// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2096// If a recoverable error occurs, return 1. If an irrecoverable error
2097// occurs, return -1. An irrecoverable error is one where tokens have been
2098// consumed in the process of trying to parse the shifter (i.e., when it is
2099// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002100int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002101 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2102 SMLoc S = Parser.getTok().getLoc();
2103 const AsmToken &Tok = Parser.getTok();
2104 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2105
Benjamin Kramer59085362011-11-06 20:37:06 +00002106 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002107 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2108 .Case("lsl", ARM_AM::lsl)
2109 .Case("lsr", ARM_AM::lsr)
2110 .Case("asr", ARM_AM::asr)
2111 .Case("ror", ARM_AM::ror)
2112 .Case("rrx", ARM_AM::rrx)
2113 .Default(ARM_AM::no_shift);
2114
2115 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002116 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002117
Jim Grosbache8606dc2011-07-13 17:50:29 +00002118 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002119
Jim Grosbache8606dc2011-07-13 17:50:29 +00002120 // The source register for the shift has already been added to the
2121 // operand list, so we need to pop it off and combine it into the shifted
2122 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002123 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002124 if (!PrevOp->isReg())
2125 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2126 int SrcReg = PrevOp->getReg();
2127 int64_t Imm = 0;
2128 int ShiftReg = 0;
2129 if (ShiftTy == ARM_AM::rrx) {
2130 // RRX Doesn't have an explicit shift amount. The encoder expects
2131 // the shift register to be the same as the source register. Seems odd,
2132 // but OK.
2133 ShiftReg = SrcReg;
2134 } else {
2135 // Figure out if this is shifted by a constant or a register (for non-RRX).
2136 if (Parser.getTok().is(AsmToken::Hash)) {
2137 Parser.Lex(); // Eat hash.
2138 SMLoc ImmLoc = Parser.getTok().getLoc();
2139 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002140 if (getParser().ParseExpression(ShiftExpr)) {
2141 Error(ImmLoc, "invalid immediate shift value");
2142 return -1;
2143 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002144 // The expression must be evaluatable as an immediate.
2145 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002146 if (!CE) {
2147 Error(ImmLoc, "invalid immediate shift value");
2148 return -1;
2149 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002150 // Range check the immediate.
2151 // lsl, ror: 0 <= imm <= 31
2152 // lsr, asr: 0 <= imm <= 32
2153 Imm = CE->getValue();
2154 if (Imm < 0 ||
2155 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2156 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002157 Error(ImmLoc, "immediate shift value out of range");
2158 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002159 }
2160 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002161 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002162 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002163 if (ShiftReg == -1) {
2164 Error (L, "expected immediate or register in shift operand");
2165 return -1;
2166 }
2167 } else {
2168 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002169 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002170 return -1;
2171 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002172 }
2173
Owen Anderson92a20222011-07-21 18:54:16 +00002174 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2175 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002176 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002177 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002178 else
2179 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2180 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002181
Jim Grosbach19906722011-07-13 18:49:30 +00002182 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002183}
2184
2185
Bill Wendling50d0f582010-11-18 23:43:05 +00002186/// Try to parse a register name. The token must be an Identifier when called.
2187/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2188/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002189///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002190/// TODO this is likely to change to allow different register types and or to
2191/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002192bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002193tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002194 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002195 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002196 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002197 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002198
Bill Wendling50d0f582010-11-18 23:43:05 +00002199 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002200
Chris Lattnere5658fa2010-10-30 04:09:10 +00002201 const AsmToken &ExclaimTok = Parser.getTok();
2202 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002203 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2204 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002205 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002206 return false;
2207 }
2208
2209 // Also check for an index operand. This is only legal for vector registers,
2210 // but that'll get caught OK in operand matching, so we don't need to
2211 // explicitly filter everything else out here.
2212 if (Parser.getTok().is(AsmToken::LBrac)) {
2213 SMLoc SIdx = Parser.getTok().getLoc();
2214 Parser.Lex(); // Eat left bracket token.
2215
2216 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002217 if (getParser().ParseExpression(ImmVal))
2218 return MatchOperand_ParseFail;
2219 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2220 if (!MCE) {
2221 TokError("immediate value expected for vector index");
2222 return MatchOperand_ParseFail;
2223 }
2224
2225 SMLoc E = Parser.getTok().getLoc();
2226 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2227 Error(E, "']' expected");
2228 return MatchOperand_ParseFail;
2229 }
2230
2231 Parser.Lex(); // Eat right bracket token.
2232
2233 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2234 SIdx, E,
2235 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002236 }
2237
Bill Wendling50d0f582010-11-18 23:43:05 +00002238 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002239}
2240
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002241/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2242/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2243/// "c5", ...
2244static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002245 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2246 // but efficient.
2247 switch (Name.size()) {
2248 default: break;
2249 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002250 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002251 return -1;
2252 switch (Name[1]) {
2253 default: return -1;
2254 case '0': return 0;
2255 case '1': return 1;
2256 case '2': return 2;
2257 case '3': return 3;
2258 case '4': return 4;
2259 case '5': return 5;
2260 case '6': return 6;
2261 case '7': return 7;
2262 case '8': return 8;
2263 case '9': return 9;
2264 }
2265 break;
2266 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002267 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268 return -1;
2269 switch (Name[2]) {
2270 default: return -1;
2271 case '0': return 10;
2272 case '1': return 11;
2273 case '2': return 12;
2274 case '3': return 13;
2275 case '4': return 14;
2276 case '5': return 15;
2277 }
2278 break;
2279 }
2280
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002281 return -1;
2282}
2283
Jim Grosbach89df9962011-08-26 21:43:41 +00002284/// parseITCondCode - Try to parse a condition code for an IT instruction.
2285ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2286parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2287 SMLoc S = Parser.getTok().getLoc();
2288 const AsmToken &Tok = Parser.getTok();
2289 if (!Tok.is(AsmToken::Identifier))
2290 return MatchOperand_NoMatch;
2291 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2292 .Case("eq", ARMCC::EQ)
2293 .Case("ne", ARMCC::NE)
2294 .Case("hs", ARMCC::HS)
2295 .Case("cs", ARMCC::HS)
2296 .Case("lo", ARMCC::LO)
2297 .Case("cc", ARMCC::LO)
2298 .Case("mi", ARMCC::MI)
2299 .Case("pl", ARMCC::PL)
2300 .Case("vs", ARMCC::VS)
2301 .Case("vc", ARMCC::VC)
2302 .Case("hi", ARMCC::HI)
2303 .Case("ls", ARMCC::LS)
2304 .Case("ge", ARMCC::GE)
2305 .Case("lt", ARMCC::LT)
2306 .Case("gt", ARMCC::GT)
2307 .Case("le", ARMCC::LE)
2308 .Case("al", ARMCC::AL)
2309 .Default(~0U);
2310 if (CC == ~0U)
2311 return MatchOperand_NoMatch;
2312 Parser.Lex(); // Eat the token.
2313
2314 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2315
2316 return MatchOperand_Success;
2317}
2318
Jim Grosbach43904292011-07-25 20:14:50 +00002319/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002320/// token must be an Identifier when called, and if it is a coprocessor
2321/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002322ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002323parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002324 SMLoc S = Parser.getTok().getLoc();
2325 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002326 if (Tok.isNot(AsmToken::Identifier))
2327 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002328
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002329 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002330 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002331 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002332
2333 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002334 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002335 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002336}
2337
Jim Grosbach43904292011-07-25 20:14:50 +00002338/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002339/// token must be an Identifier when called, and if it is a coprocessor
2340/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002341ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002342parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002343 SMLoc S = Parser.getTok().getLoc();
2344 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002345 if (Tok.isNot(AsmToken::Identifier))
2346 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002347
2348 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2349 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002350 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002351
2352 Parser.Lex(); // Eat identifier token.
2353 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002354 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002355}
2356
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002357/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2358/// coproc_option : '{' imm0_255 '}'
2359ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2360parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2361 SMLoc S = Parser.getTok().getLoc();
2362
2363 // If this isn't a '{', this isn't a coprocessor immediate operand.
2364 if (Parser.getTok().isNot(AsmToken::LCurly))
2365 return MatchOperand_NoMatch;
2366 Parser.Lex(); // Eat the '{'
2367
2368 const MCExpr *Expr;
2369 SMLoc Loc = Parser.getTok().getLoc();
2370 if (getParser().ParseExpression(Expr)) {
2371 Error(Loc, "illegal expression");
2372 return MatchOperand_ParseFail;
2373 }
2374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2375 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2376 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2377 return MatchOperand_ParseFail;
2378 }
2379 int Val = CE->getValue();
2380
2381 // Check for and consume the closing '}'
2382 if (Parser.getTok().isNot(AsmToken::RCurly))
2383 return MatchOperand_ParseFail;
2384 SMLoc E = Parser.getTok().getLoc();
2385 Parser.Lex(); // Eat the '}'
2386
2387 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2388 return MatchOperand_Success;
2389}
2390
Jim Grosbachd0588e22011-09-14 18:08:35 +00002391// For register list parsing, we need to map from raw GPR register numbering
2392// to the enumeration values. The enumeration values aren't sorted by
2393// register number due to our using "sp", "lr" and "pc" as canonical names.
2394static unsigned getNextRegister(unsigned Reg) {
2395 // If this is a GPR, we need to do it manually, otherwise we can rely
2396 // on the sort ordering of the enumeration since the other reg-classes
2397 // are sane.
2398 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2399 return Reg + 1;
2400 switch(Reg) {
2401 default: assert(0 && "Invalid GPR number!");
2402 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2403 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2404 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2405 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2406 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2407 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2408 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2409 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2410 }
2411}
2412
Jim Grosbachce485e72011-11-11 21:27:40 +00002413// Return the low-subreg of a given Q register.
2414static unsigned getDRegFromQReg(unsigned QReg) {
2415 switch (QReg) {
2416 default: llvm_unreachable("expected a Q register!");
2417 case ARM::Q0: return ARM::D0;
2418 case ARM::Q1: return ARM::D2;
2419 case ARM::Q2: return ARM::D4;
2420 case ARM::Q3: return ARM::D6;
2421 case ARM::Q4: return ARM::D8;
2422 case ARM::Q5: return ARM::D10;
2423 case ARM::Q6: return ARM::D12;
2424 case ARM::Q7: return ARM::D14;
2425 case ARM::Q8: return ARM::D16;
2426 case ARM::Q9: return ARM::D19;
2427 case ARM::Q10: return ARM::D20;
2428 case ARM::Q11: return ARM::D22;
2429 case ARM::Q12: return ARM::D24;
2430 case ARM::Q13: return ARM::D26;
2431 case ARM::Q14: return ARM::D28;
2432 case ARM::Q15: return ARM::D30;
2433 }
2434}
2435
Jim Grosbachd0588e22011-09-14 18:08:35 +00002436/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002437bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002438parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002439 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002440 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002441 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002442 Parser.Lex(); // Eat '{' token.
2443 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002444
Jim Grosbachd0588e22011-09-14 18:08:35 +00002445 // Check the first register in the list to see what register class
2446 // this is a list of.
2447 int Reg = tryParseRegister();
2448 if (Reg == -1)
2449 return Error(RegLoc, "register expected");
2450
Jim Grosbachce485e72011-11-11 21:27:40 +00002451 // The reglist instructions have at most 16 registers, so reserve
2452 // space for that many.
2453 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2454
2455 // Allow Q regs and just interpret them as the two D sub-registers.
2456 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2457 Reg = getDRegFromQReg(Reg);
2458 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2459 ++Reg;
2460 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002461 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002462 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2463 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2464 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2465 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2466 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2467 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2468 else
2469 return Error(RegLoc, "invalid register in register list");
2470
Jim Grosbachce485e72011-11-11 21:27:40 +00002471 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002472 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002473
Jim Grosbachd0588e22011-09-14 18:08:35 +00002474 // This starts immediately after the first register token in the list,
2475 // so we can see either a comma or a minus (range separator) as a legal
2476 // next token.
2477 while (Parser.getTok().is(AsmToken::Comma) ||
2478 Parser.getTok().is(AsmToken::Minus)) {
2479 if (Parser.getTok().is(AsmToken::Minus)) {
2480 Parser.Lex(); // Eat the comma.
2481 SMLoc EndLoc = Parser.getTok().getLoc();
2482 int EndReg = tryParseRegister();
2483 if (EndReg == -1)
2484 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002485 // Allow Q regs and just interpret them as the two D sub-registers.
2486 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2487 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002488 // If the register is the same as the start reg, there's nothing
2489 // more to do.
2490 if (Reg == EndReg)
2491 continue;
2492 // The register must be in the same register class as the first.
2493 if (!RC->contains(EndReg))
2494 return Error(EndLoc, "invalid register in register list");
2495 // Ranges must go from low to high.
2496 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2497 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002498
Jim Grosbachd0588e22011-09-14 18:08:35 +00002499 // Add all the registers in the range to the register list.
2500 while (Reg != EndReg) {
2501 Reg = getNextRegister(Reg);
2502 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2503 }
2504 continue;
2505 }
2506 Parser.Lex(); // Eat the comma.
2507 RegLoc = Parser.getTok().getLoc();
2508 int OldReg = Reg;
2509 Reg = tryParseRegister();
2510 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002511 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002512 // Allow Q regs and just interpret them as the two D sub-registers.
2513 bool isQReg = false;
2514 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2515 Reg = getDRegFromQReg(Reg);
2516 isQReg = true;
2517 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002518 // The register must be in the same register class as the first.
2519 if (!RC->contains(Reg))
2520 return Error(RegLoc, "invalid register in register list");
2521 // List must be monotonically increasing.
2522 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2523 return Error(RegLoc, "register list not in ascending order");
2524 // VFP register lists must also be contiguous.
2525 // It's OK to use the enumeration values directly here rather, as the
2526 // VFP register classes have the enum sorted properly.
2527 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2528 Reg != OldReg + 1)
2529 return Error(RegLoc, "non-contiguous register range");
2530 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002531 if (isQReg)
2532 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002533 }
2534
Jim Grosbachd0588e22011-09-14 18:08:35 +00002535 SMLoc E = Parser.getTok().getLoc();
2536 if (Parser.getTok().isNot(AsmToken::RCurly))
2537 return Error(E, "'}' expected");
2538 Parser.Lex(); // Eat '}' token.
2539
Bill Wendling50d0f582010-11-18 23:43:05 +00002540 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2541 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002542}
2543
Jim Grosbach862019c2011-10-18 23:02:30 +00002544// parse a vector register list
2545ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2546parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2547 if(Parser.getTok().isNot(AsmToken::LCurly))
2548 return MatchOperand_NoMatch;
2549
2550 SMLoc S = Parser.getTok().getLoc();
2551 Parser.Lex(); // Eat '{' token.
2552 SMLoc RegLoc = Parser.getTok().getLoc();
2553
2554 int Reg = tryParseRegister();
2555 if (Reg == -1) {
2556 Error(RegLoc, "register expected");
2557 return MatchOperand_ParseFail;
2558 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002559 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002560 unsigned FirstReg = Reg;
2561 // The list is of D registers, but we also allow Q regs and just interpret
2562 // them as the two D sub-registers.
2563 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2564 FirstReg = Reg = getDRegFromQReg(Reg);
2565 ++Reg;
2566 ++Count;
2567 }
2568
Jim Grosbach862019c2011-10-18 23:02:30 +00002569 while (Parser.getTok().is(AsmToken::Comma)) {
2570 Parser.Lex(); // Eat the comma.
2571 RegLoc = Parser.getTok().getLoc();
2572 int OldReg = Reg;
2573 Reg = tryParseRegister();
2574 if (Reg == -1) {
2575 Error(RegLoc, "register expected");
2576 return MatchOperand_ParseFail;
2577 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002578 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002579 // It's OK to use the enumeration values directly here rather, as the
2580 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002581 //
2582 // The list is of D registers, but we also allow Q regs and just interpret
2583 // them as the two D sub-registers.
2584 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2585 Reg = getDRegFromQReg(Reg);
2586 if (Reg != OldReg + 1) {
2587 Error(RegLoc, "non-contiguous register range");
2588 return MatchOperand_ParseFail;
2589 }
2590 ++Reg;
2591 Count += 2;
2592 continue;
2593 }
2594 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002595 if (Reg != OldReg + 1) {
2596 Error(RegLoc, "non-contiguous register range");
2597 return MatchOperand_ParseFail;
2598 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002599 ++Count;
2600 }
2601
2602 SMLoc E = Parser.getTok().getLoc();
2603 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2604 Error(E, "'}' expected");
2605 return MatchOperand_ParseFail;
2606 }
2607 Parser.Lex(); // Eat '}' token.
2608
2609 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2610 return MatchOperand_Success;
2611}
2612
Jim Grosbach43904292011-07-25 20:14:50 +00002613/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002614ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002615parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002616 SMLoc S = Parser.getTok().getLoc();
2617 const AsmToken &Tok = Parser.getTok();
2618 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2619 StringRef OptStr = Tok.getString();
2620
2621 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2622 .Case("sy", ARM_MB::SY)
2623 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002624 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002625 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002626 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002627 .Case("ishst", ARM_MB::ISHST)
2628 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002629 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002630 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002631 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002632 .Case("osh", ARM_MB::OSH)
2633 .Case("oshst", ARM_MB::OSHST)
2634 .Default(~0U);
2635
2636 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002637 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002638
2639 Parser.Lex(); // Eat identifier token.
2640 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002641 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002642}
2643
Jim Grosbach43904292011-07-25 20:14:50 +00002644/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002645ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002646parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002647 SMLoc S = Parser.getTok().getLoc();
2648 const AsmToken &Tok = Parser.getTok();
2649 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2650 StringRef IFlagsStr = Tok.getString();
2651
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002652 // An iflags string of "none" is interpreted to mean that none of the AIF
2653 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002654 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002655 if (IFlagsStr != "none") {
2656 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2657 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2658 .Case("a", ARM_PROC::A)
2659 .Case("i", ARM_PROC::I)
2660 .Case("f", ARM_PROC::F)
2661 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002662
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002663 // If some specific iflag is already set, it means that some letter is
2664 // present more than once, this is not acceptable.
2665 if (Flag == ~0U || (IFlags & Flag))
2666 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002667
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002668 IFlags |= Flag;
2669 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002670 }
2671
2672 Parser.Lex(); // Eat identifier token.
2673 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2674 return MatchOperand_Success;
2675}
2676
Jim Grosbach43904292011-07-25 20:14:50 +00002677/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002678ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002679parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002680 SMLoc S = Parser.getTok().getLoc();
2681 const AsmToken &Tok = Parser.getTok();
2682 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2683 StringRef Mask = Tok.getString();
2684
James Molloyacad68d2011-09-28 14:21:38 +00002685 if (isMClass()) {
2686 // See ARMv6-M 10.1.1
2687 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2688 .Case("apsr", 0)
2689 .Case("iapsr", 1)
2690 .Case("eapsr", 2)
2691 .Case("xpsr", 3)
2692 .Case("ipsr", 5)
2693 .Case("epsr", 6)
2694 .Case("iepsr", 7)
2695 .Case("msp", 8)
2696 .Case("psp", 9)
2697 .Case("primask", 16)
2698 .Case("basepri", 17)
2699 .Case("basepri_max", 18)
2700 .Case("faultmask", 19)
2701 .Case("control", 20)
2702 .Default(~0U);
2703
2704 if (FlagsVal == ~0U)
2705 return MatchOperand_NoMatch;
2706
2707 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2708 // basepri, basepri_max and faultmask only valid for V7m.
2709 return MatchOperand_NoMatch;
2710
2711 Parser.Lex(); // Eat identifier token.
2712 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2713 return MatchOperand_Success;
2714 }
2715
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002716 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2717 size_t Start = 0, Next = Mask.find('_');
2718 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002719 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002720 if (Next != StringRef::npos)
2721 Flags = Mask.slice(Next+1, Mask.size());
2722
2723 // FlagsVal contains the complete mask:
2724 // 3-0: Mask
2725 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2726 unsigned FlagsVal = 0;
2727
2728 if (SpecReg == "apsr") {
2729 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002730 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002731 .Case("g", 0x4) // same as CPSR_s
2732 .Case("nzcvqg", 0xc) // same as CPSR_fs
2733 .Default(~0U);
2734
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002735 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002736 if (!Flags.empty())
2737 return MatchOperand_NoMatch;
2738 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002739 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002740 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002741 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002742 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2743 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002744 for (int i = 0, e = Flags.size(); i != e; ++i) {
2745 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2746 .Case("c", 1)
2747 .Case("x", 2)
2748 .Case("s", 4)
2749 .Case("f", 8)
2750 .Default(~0U);
2751
2752 // If some specific flag is already set, it means that some letter is
2753 // present more than once, this is not acceptable.
2754 if (FlagsVal == ~0U || (FlagsVal & Flag))
2755 return MatchOperand_NoMatch;
2756 FlagsVal |= Flag;
2757 }
2758 } else // No match for special register.
2759 return MatchOperand_NoMatch;
2760
Owen Anderson7784f1d2011-10-21 18:43:28 +00002761 // Special register without flags is NOT equivalent to "fc" flags.
2762 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2763 // two lines would enable gas compatibility at the expense of breaking
2764 // round-tripping.
2765 //
2766 // if (!FlagsVal)
2767 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002768
2769 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2770 if (SpecReg == "spsr")
2771 FlagsVal |= 16;
2772
2773 Parser.Lex(); // Eat identifier token.
2774 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2775 return MatchOperand_Success;
2776}
2777
Jim Grosbachf6c05252011-07-21 17:23:04 +00002778ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2779parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2780 int Low, int High) {
2781 const AsmToken &Tok = Parser.getTok();
2782 if (Tok.isNot(AsmToken::Identifier)) {
2783 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2784 return MatchOperand_ParseFail;
2785 }
2786 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002787 std::string LowerOp = Op.lower();
2788 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002789 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2790 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2791 return MatchOperand_ParseFail;
2792 }
2793 Parser.Lex(); // Eat shift type token.
2794
2795 // There must be a '#' and a shift amount.
2796 if (Parser.getTok().isNot(AsmToken::Hash)) {
2797 Error(Parser.getTok().getLoc(), "'#' expected");
2798 return MatchOperand_ParseFail;
2799 }
2800 Parser.Lex(); // Eat hash token.
2801
2802 const MCExpr *ShiftAmount;
2803 SMLoc Loc = Parser.getTok().getLoc();
2804 if (getParser().ParseExpression(ShiftAmount)) {
2805 Error(Loc, "illegal expression");
2806 return MatchOperand_ParseFail;
2807 }
2808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2809 if (!CE) {
2810 Error(Loc, "constant expression expected");
2811 return MatchOperand_ParseFail;
2812 }
2813 int Val = CE->getValue();
2814 if (Val < Low || Val > High) {
2815 Error(Loc, "immediate value out of range");
2816 return MatchOperand_ParseFail;
2817 }
2818
2819 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2820
2821 return MatchOperand_Success;
2822}
2823
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002824ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2825parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2826 const AsmToken &Tok = Parser.getTok();
2827 SMLoc S = Tok.getLoc();
2828 if (Tok.isNot(AsmToken::Identifier)) {
2829 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2830 return MatchOperand_ParseFail;
2831 }
2832 int Val = StringSwitch<int>(Tok.getString())
2833 .Case("be", 1)
2834 .Case("le", 0)
2835 .Default(-1);
2836 Parser.Lex(); // Eat the token.
2837
2838 if (Val == -1) {
2839 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2840 return MatchOperand_ParseFail;
2841 }
2842 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2843 getContext()),
2844 S, Parser.getTok().getLoc()));
2845 return MatchOperand_Success;
2846}
2847
Jim Grosbach580f4a92011-07-25 22:20:28 +00002848/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2849/// instructions. Legal values are:
2850/// lsl #n 'n' in [0,31]
2851/// asr #n 'n' in [1,32]
2852/// n == 32 encoded as n == 0.
2853ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2854parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2855 const AsmToken &Tok = Parser.getTok();
2856 SMLoc S = Tok.getLoc();
2857 if (Tok.isNot(AsmToken::Identifier)) {
2858 Error(S, "shift operator 'asr' or 'lsl' expected");
2859 return MatchOperand_ParseFail;
2860 }
2861 StringRef ShiftName = Tok.getString();
2862 bool isASR;
2863 if (ShiftName == "lsl" || ShiftName == "LSL")
2864 isASR = false;
2865 else if (ShiftName == "asr" || ShiftName == "ASR")
2866 isASR = true;
2867 else {
2868 Error(S, "shift operator 'asr' or 'lsl' expected");
2869 return MatchOperand_ParseFail;
2870 }
2871 Parser.Lex(); // Eat the operator.
2872
2873 // A '#' and a shift amount.
2874 if (Parser.getTok().isNot(AsmToken::Hash)) {
2875 Error(Parser.getTok().getLoc(), "'#' expected");
2876 return MatchOperand_ParseFail;
2877 }
2878 Parser.Lex(); // Eat hash token.
2879
2880 const MCExpr *ShiftAmount;
2881 SMLoc E = Parser.getTok().getLoc();
2882 if (getParser().ParseExpression(ShiftAmount)) {
2883 Error(E, "malformed shift expression");
2884 return MatchOperand_ParseFail;
2885 }
2886 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2887 if (!CE) {
2888 Error(E, "shift amount must be an immediate");
2889 return MatchOperand_ParseFail;
2890 }
2891
2892 int64_t Val = CE->getValue();
2893 if (isASR) {
2894 // Shift amount must be in [1,32]
2895 if (Val < 1 || Val > 32) {
2896 Error(E, "'asr' shift amount must be in range [1,32]");
2897 return MatchOperand_ParseFail;
2898 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002899 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2900 if (isThumb() && Val == 32) {
2901 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2902 return MatchOperand_ParseFail;
2903 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002904 if (Val == 32) Val = 0;
2905 } else {
2906 // Shift amount must be in [1,32]
2907 if (Val < 0 || Val > 31) {
2908 Error(E, "'lsr' shift amount must be in range [0,31]");
2909 return MatchOperand_ParseFail;
2910 }
2911 }
2912
2913 E = Parser.getTok().getLoc();
2914 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2915
2916 return MatchOperand_Success;
2917}
2918
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002919/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2920/// of instructions. Legal values are:
2921/// ror #n 'n' in {0, 8, 16, 24}
2922ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2923parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2924 const AsmToken &Tok = Parser.getTok();
2925 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002926 if (Tok.isNot(AsmToken::Identifier))
2927 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002928 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002929 if (ShiftName != "ror" && ShiftName != "ROR")
2930 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002931 Parser.Lex(); // Eat the operator.
2932
2933 // A '#' and a rotate amount.
2934 if (Parser.getTok().isNot(AsmToken::Hash)) {
2935 Error(Parser.getTok().getLoc(), "'#' expected");
2936 return MatchOperand_ParseFail;
2937 }
2938 Parser.Lex(); // Eat hash token.
2939
2940 const MCExpr *ShiftAmount;
2941 SMLoc E = Parser.getTok().getLoc();
2942 if (getParser().ParseExpression(ShiftAmount)) {
2943 Error(E, "malformed rotate expression");
2944 return MatchOperand_ParseFail;
2945 }
2946 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2947 if (!CE) {
2948 Error(E, "rotate amount must be an immediate");
2949 return MatchOperand_ParseFail;
2950 }
2951
2952 int64_t Val = CE->getValue();
2953 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2954 // normally, zero is represented in asm by omitting the rotate operand
2955 // entirely.
2956 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2957 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2958 return MatchOperand_ParseFail;
2959 }
2960
2961 E = Parser.getTok().getLoc();
2962 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2963
2964 return MatchOperand_Success;
2965}
2966
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002967ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2968parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2969 SMLoc S = Parser.getTok().getLoc();
2970 // The bitfield descriptor is really two operands, the LSB and the width.
2971 if (Parser.getTok().isNot(AsmToken::Hash)) {
2972 Error(Parser.getTok().getLoc(), "'#' expected");
2973 return MatchOperand_ParseFail;
2974 }
2975 Parser.Lex(); // Eat hash token.
2976
2977 const MCExpr *LSBExpr;
2978 SMLoc E = Parser.getTok().getLoc();
2979 if (getParser().ParseExpression(LSBExpr)) {
2980 Error(E, "malformed immediate expression");
2981 return MatchOperand_ParseFail;
2982 }
2983 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2984 if (!CE) {
2985 Error(E, "'lsb' operand must be an immediate");
2986 return MatchOperand_ParseFail;
2987 }
2988
2989 int64_t LSB = CE->getValue();
2990 // The LSB must be in the range [0,31]
2991 if (LSB < 0 || LSB > 31) {
2992 Error(E, "'lsb' operand must be in the range [0,31]");
2993 return MatchOperand_ParseFail;
2994 }
2995 E = Parser.getTok().getLoc();
2996
2997 // Expect another immediate operand.
2998 if (Parser.getTok().isNot(AsmToken::Comma)) {
2999 Error(Parser.getTok().getLoc(), "too few operands");
3000 return MatchOperand_ParseFail;
3001 }
3002 Parser.Lex(); // Eat hash token.
3003 if (Parser.getTok().isNot(AsmToken::Hash)) {
3004 Error(Parser.getTok().getLoc(), "'#' expected");
3005 return MatchOperand_ParseFail;
3006 }
3007 Parser.Lex(); // Eat hash token.
3008
3009 const MCExpr *WidthExpr;
3010 if (getParser().ParseExpression(WidthExpr)) {
3011 Error(E, "malformed immediate expression");
3012 return MatchOperand_ParseFail;
3013 }
3014 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3015 if (!CE) {
3016 Error(E, "'width' operand must be an immediate");
3017 return MatchOperand_ParseFail;
3018 }
3019
3020 int64_t Width = CE->getValue();
3021 // The LSB must be in the range [1,32-lsb]
3022 if (Width < 1 || Width > 32 - LSB) {
3023 Error(E, "'width' operand must be in the range [1,32-lsb]");
3024 return MatchOperand_ParseFail;
3025 }
3026 E = Parser.getTok().getLoc();
3027
3028 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3029
3030 return MatchOperand_Success;
3031}
3032
Jim Grosbach7ce05792011-08-03 23:50:40 +00003033ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3034parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3035 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003036 // postidx_reg := '+' register {, shift}
3037 // | '-' register {, shift}
3038 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003039
3040 // This method must return MatchOperand_NoMatch without consuming any tokens
3041 // in the case where there is no match, as other alternatives take other
3042 // parse methods.
3043 AsmToken Tok = Parser.getTok();
3044 SMLoc S = Tok.getLoc();
3045 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003046 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003047 int Reg = -1;
3048 if (Tok.is(AsmToken::Plus)) {
3049 Parser.Lex(); // Eat the '+' token.
3050 haveEaten = true;
3051 } else if (Tok.is(AsmToken::Minus)) {
3052 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003053 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003054 haveEaten = true;
3055 }
3056 if (Parser.getTok().is(AsmToken::Identifier))
3057 Reg = tryParseRegister();
3058 if (Reg == -1) {
3059 if (!haveEaten)
3060 return MatchOperand_NoMatch;
3061 Error(Parser.getTok().getLoc(), "register expected");
3062 return MatchOperand_ParseFail;
3063 }
3064 SMLoc E = Parser.getTok().getLoc();
3065
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003066 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3067 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003068 if (Parser.getTok().is(AsmToken::Comma)) {
3069 Parser.Lex(); // Eat the ','.
3070 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3071 return MatchOperand_ParseFail;
3072 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003073
3074 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3075 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003076
3077 return MatchOperand_Success;
3078}
3079
Jim Grosbach251bf252011-08-10 21:56:18 +00003080ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3081parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3082 // Check for a post-index addressing register operand. Specifically:
3083 // am3offset := '+' register
3084 // | '-' register
3085 // | register
3086 // | # imm
3087 // | # + imm
3088 // | # - imm
3089
3090 // This method must return MatchOperand_NoMatch without consuming any tokens
3091 // in the case where there is no match, as other alternatives take other
3092 // parse methods.
3093 AsmToken Tok = Parser.getTok();
3094 SMLoc S = Tok.getLoc();
3095
3096 // Do immediates first, as we always parse those if we have a '#'.
3097 if (Parser.getTok().is(AsmToken::Hash)) {
3098 Parser.Lex(); // Eat the '#'.
3099 // Explicitly look for a '-', as we need to encode negative zero
3100 // differently.
3101 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3102 const MCExpr *Offset;
3103 if (getParser().ParseExpression(Offset))
3104 return MatchOperand_ParseFail;
3105 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3106 if (!CE) {
3107 Error(S, "constant expression expected");
3108 return MatchOperand_ParseFail;
3109 }
3110 SMLoc E = Tok.getLoc();
3111 // Negative zero is encoded as the flag value INT32_MIN.
3112 int32_t Val = CE->getValue();
3113 if (isNegative && Val == 0)
3114 Val = INT32_MIN;
3115
3116 Operands.push_back(
3117 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3118
3119 return MatchOperand_Success;
3120 }
3121
3122
3123 bool haveEaten = false;
3124 bool isAdd = true;
3125 int Reg = -1;
3126 if (Tok.is(AsmToken::Plus)) {
3127 Parser.Lex(); // Eat the '+' token.
3128 haveEaten = true;
3129 } else if (Tok.is(AsmToken::Minus)) {
3130 Parser.Lex(); // Eat the '-' token.
3131 isAdd = false;
3132 haveEaten = true;
3133 }
3134 if (Parser.getTok().is(AsmToken::Identifier))
3135 Reg = tryParseRegister();
3136 if (Reg == -1) {
3137 if (!haveEaten)
3138 return MatchOperand_NoMatch;
3139 Error(Parser.getTok().getLoc(), "register expected");
3140 return MatchOperand_ParseFail;
3141 }
3142 SMLoc E = Parser.getTok().getLoc();
3143
3144 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3145 0, S, E));
3146
3147 return MatchOperand_Success;
3148}
3149
Jim Grosbacha77295d2011-09-08 22:07:06 +00003150/// cvtT2LdrdPre - 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::
3154cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3155 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3156 // Rt, Rt2
3157 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3158 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3159 // Create a writeback register dummy placeholder.
3160 Inst.addOperand(MCOperand::CreateReg(0));
3161 // addr
3162 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3163 // pred
3164 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3165 return true;
3166}
3167
3168/// cvtT2StrdPre - Convert parsed operands to MCInst.
3169/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3170/// when they refer multiple MIOperands inside a single one.
3171bool ARMAsmParser::
3172cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3173 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3174 // Create a writeback register dummy placeholder.
3175 Inst.addOperand(MCOperand::CreateReg(0));
3176 // Rt, Rt2
3177 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3178 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3179 // addr
3180 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3181 // pred
3182 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3183 return true;
3184}
3185
Jim Grosbacheeec0252011-09-08 00:39:19 +00003186/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3187/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3188/// when they refer multiple MIOperands inside a single one.
3189bool ARMAsmParser::
3190cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3191 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3192 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3193
3194 // Create a writeback register dummy placeholder.
3195 Inst.addOperand(MCOperand::CreateImm(0));
3196
3197 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3198 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3199 return true;
3200}
3201
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003202/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3203/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3204/// when they refer multiple MIOperands inside a single one.
3205bool ARMAsmParser::
3206cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3207 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3208 // Create a writeback register dummy placeholder.
3209 Inst.addOperand(MCOperand::CreateImm(0));
3210 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3211 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3212 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3213 return true;
3214}
3215
Jim Grosbach1355cf12011-07-26 17:10:22 +00003216/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003217/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3218/// when they refer multiple MIOperands inside a single one.
3219bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003220cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003221 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3222 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3223
3224 // Create a writeback register dummy placeholder.
3225 Inst.addOperand(MCOperand::CreateImm(0));
3226
Jim Grosbach7ce05792011-08-03 23:50:40 +00003227 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003228 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3229 return true;
3230}
3231
Owen Anderson9ab0f252011-08-26 20:43:14 +00003232/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3233/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3234/// when they refer multiple MIOperands inside a single one.
3235bool ARMAsmParser::
3236cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3237 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3238 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3239
3240 // Create a writeback register dummy placeholder.
3241 Inst.addOperand(MCOperand::CreateImm(0));
3242
3243 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3244 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3245 return true;
3246}
3247
3248
Jim Grosbach548340c2011-08-11 19:22:40 +00003249/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3250/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3251/// when they refer multiple MIOperands inside a single one.
3252bool ARMAsmParser::
3253cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3254 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3255 // Create a writeback register dummy placeholder.
3256 Inst.addOperand(MCOperand::CreateImm(0));
3257 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3258 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3259 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3260 return true;
3261}
3262
Jim Grosbach1355cf12011-07-26 17:10:22 +00003263/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003264/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3265/// when they refer multiple MIOperands inside a single one.
3266bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003267cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003268 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3269 // Create a writeback register dummy placeholder.
3270 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003271 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3272 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3273 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003274 return true;
3275}
3276
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003277/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3278/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3279/// when they refer multiple MIOperands inside a single one.
3280bool ARMAsmParser::
3281cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3282 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3283 // Create a writeback register dummy placeholder.
3284 Inst.addOperand(MCOperand::CreateImm(0));
3285 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3286 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3287 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3288 return true;
3289}
3290
Jim Grosbach7ce05792011-08-03 23:50:40 +00003291/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3292/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3293/// when they refer multiple MIOperands inside a single one.
3294bool ARMAsmParser::
3295cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3296 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3297 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003298 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003299 // Create a writeback register dummy placeholder.
3300 Inst.addOperand(MCOperand::CreateImm(0));
3301 // addr
3302 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3303 // offset
3304 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3305 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003306 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3307 return true;
3308}
3309
Jim Grosbach7ce05792011-08-03 23:50:40 +00003310/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003311/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3312/// when they refer multiple MIOperands inside a single one.
3313bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003314cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3315 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3316 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003317 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003318 // Create a writeback register dummy placeholder.
3319 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003320 // addr
3321 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3322 // offset
3323 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3324 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003325 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3326 return true;
3327}
3328
Jim Grosbach7ce05792011-08-03 23:50:40 +00003329/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003330/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3331/// when they refer multiple MIOperands inside a single one.
3332bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003333cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3334 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003335 // Create a writeback register dummy placeholder.
3336 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003337 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003338 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003339 // addr
3340 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3341 // offset
3342 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3343 // pred
3344 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3345 return true;
3346}
3347
3348/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3349/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3350/// when they refer multiple MIOperands inside a single one.
3351bool ARMAsmParser::
3352cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3353 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3354 // Create a writeback register dummy placeholder.
3355 Inst.addOperand(MCOperand::CreateImm(0));
3356 // Rt
3357 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3358 // addr
3359 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3360 // offset
3361 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3362 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003363 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3364 return true;
3365}
3366
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003367/// cvtLdrdPre - 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::
3371cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3372 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 // Rt, Rt2
3374 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3375 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3376 // Create a writeback register dummy placeholder.
3377 Inst.addOperand(MCOperand::CreateImm(0));
3378 // addr
3379 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3380 // pred
3381 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3382 return true;
3383}
3384
Jim Grosbach14605d12011-08-11 20:28:23 +00003385/// cvtStrdPre - Convert parsed operands to MCInst.
3386/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3387/// when they refer multiple MIOperands inside a single one.
3388bool ARMAsmParser::
3389cvtStrdPre(MCInst &Inst, unsigned Opcode,
3390 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3391 // Create a writeback register dummy placeholder.
3392 Inst.addOperand(MCOperand::CreateImm(0));
3393 // Rt, Rt2
3394 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3395 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3396 // addr
3397 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3398 // pred
3399 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3400 return true;
3401}
3402
Jim Grosbach623a4542011-08-10 22:42:16 +00003403/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3404/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3405/// when they refer multiple MIOperands inside a single one.
3406bool ARMAsmParser::
3407cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3408 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3409 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3410 // Create a writeback register dummy placeholder.
3411 Inst.addOperand(MCOperand::CreateImm(0));
3412 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3413 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3414 return true;
3415}
3416
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003417/// cvtThumbMultiple- Convert parsed operands to MCInst.
3418/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3419/// when they refer multiple MIOperands inside a single one.
3420bool ARMAsmParser::
3421cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3422 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3423 // The second source operand must be the same register as the destination
3424 // operand.
3425 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003426 (((ARMOperand*)Operands[3])->getReg() !=
3427 ((ARMOperand*)Operands[5])->getReg()) &&
3428 (((ARMOperand*)Operands[3])->getReg() !=
3429 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003430 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003431 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003432 return false;
3433 }
3434 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3435 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003436 // If we have a three-operand form, make sure to set Rn to be the operand
3437 // that isn't the same as Rd.
3438 unsigned RegOp = 4;
3439 if (Operands.size() == 6 &&
3440 ((ARMOperand*)Operands[4])->getReg() ==
3441 ((ARMOperand*)Operands[3])->getReg())
3442 RegOp = 5;
3443 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3444 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003445 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3446
3447 return true;
3448}
Jim Grosbach623a4542011-08-10 22:42:16 +00003449
Jim Grosbach12431322011-10-24 22:16:58 +00003450bool ARMAsmParser::
3451cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3452 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3453 // Vd
3454 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3455 // Create a writeback register dummy placeholder.
3456 Inst.addOperand(MCOperand::CreateImm(0));
3457 // Vn
3458 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3459 // pred
3460 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3461 return true;
3462}
3463
3464bool ARMAsmParser::
3465cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3466 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 // Vd
3468 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3469 // Create a writeback register dummy placeholder.
3470 Inst.addOperand(MCOperand::CreateImm(0));
3471 // Vn
3472 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3473 // Vm
3474 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3475 // pred
3476 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3477 return true;
3478}
3479
Jim Grosbach4334e032011-10-31 21:50:31 +00003480bool ARMAsmParser::
3481cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3482 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3483 // Create a writeback register dummy placeholder.
3484 Inst.addOperand(MCOperand::CreateImm(0));
3485 // Vn
3486 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3487 // Vt
3488 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3489 // pred
3490 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3491 return true;
3492}
3493
3494bool ARMAsmParser::
3495cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3496 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3497 // Create a writeback register dummy placeholder.
3498 Inst.addOperand(MCOperand::CreateImm(0));
3499 // Vn
3500 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3501 // Vm
3502 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3503 // Vt
3504 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3505 // pred
3506 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3507 return true;
3508}
3509
Bill Wendlinge7176102010-11-06 22:36:58 +00003510/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003511/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003512bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003513parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003514 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003515 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003516 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003517 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003518 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003519
Sean Callanan18b83232010-01-19 21:44:56 +00003520 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003521 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003522 if (BaseRegNum == -1)
3523 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003524
Daniel Dunbar05710932011-01-18 05:34:17 +00003525 // The next token must either be a comma or a closing bracket.
3526 const AsmToken &Tok = Parser.getTok();
3527 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003528 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003529
Jim Grosbach7ce05792011-08-03 23:50:40 +00003530 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003531 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003532 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003533
Jim Grosbach7ce05792011-08-03 23:50:40 +00003534 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003535 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003536
Jim Grosbachfb12f352011-09-19 18:42:21 +00003537 // If there's a pre-indexing writeback marker, '!', just add it as a token
3538 // operand. It's rather odd, but syntactically valid.
3539 if (Parser.getTok().is(AsmToken::Exclaim)) {
3540 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3541 Parser.Lex(); // Eat the '!'.
3542 }
3543
Jim Grosbach7ce05792011-08-03 23:50:40 +00003544 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003545 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003546
Jim Grosbach7ce05792011-08-03 23:50:40 +00003547 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3548 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003549
Jim Grosbach57dcb852011-10-11 17:29:55 +00003550 // If we have a ':', it's an alignment specifier.
3551 if (Parser.getTok().is(AsmToken::Colon)) {
3552 Parser.Lex(); // Eat the ':'.
3553 E = Parser.getTok().getLoc();
3554
3555 const MCExpr *Expr;
3556 if (getParser().ParseExpression(Expr))
3557 return true;
3558
3559 // The expression has to be a constant. Memory references with relocations
3560 // don't come through here, as they use the <label> forms of the relevant
3561 // instructions.
3562 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3563 if (!CE)
3564 return Error (E, "constant expression expected");
3565
3566 unsigned Align = 0;
3567 switch (CE->getValue()) {
3568 default:
3569 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3570 case 64: Align = 8; break;
3571 case 128: Align = 16; break;
3572 case 256: Align = 32; break;
3573 }
3574
3575 // Now we should have the closing ']'
3576 E = Parser.getTok().getLoc();
3577 if (Parser.getTok().isNot(AsmToken::RBrac))
3578 return Error(E, "']' expected");
3579 Parser.Lex(); // Eat right bracket token.
3580
3581 // Don't worry about range checking the value here. That's handled by
3582 // the is*() predicates.
3583 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3584 ARM_AM::no_shift, 0, Align,
3585 false, S, E));
3586
3587 // If there's a pre-indexing writeback marker, '!', just add it as a token
3588 // operand.
3589 if (Parser.getTok().is(AsmToken::Exclaim)) {
3590 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3591 Parser.Lex(); // Eat the '!'.
3592 }
3593
3594 return false;
3595 }
3596
3597 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598 // offset.
3599 if (Parser.getTok().is(AsmToken::Hash)) {
3600 Parser.Lex(); // Eat the '#'.
3601 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003602
Owen Anderson0da10cf2011-08-29 19:36:44 +00003603 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003604 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003605 if (getParser().ParseExpression(Offset))
3606 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003607
3608 // The expression has to be a constant. Memory references with relocations
3609 // don't come through here, as they use the <label> forms of the relevant
3610 // instructions.
3611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3612 if (!CE)
3613 return Error (E, "constant expression expected");
3614
Owen Anderson0da10cf2011-08-29 19:36:44 +00003615 // If the constant was #-0, represent it as INT32_MIN.
3616 int32_t Val = CE->getValue();
3617 if (isNegative && Val == 0)
3618 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3619
Jim Grosbach7ce05792011-08-03 23:50:40 +00003620 // Now we should have the closing ']'
3621 E = Parser.getTok().getLoc();
3622 if (Parser.getTok().isNot(AsmToken::RBrac))
3623 return Error(E, "']' expected");
3624 Parser.Lex(); // Eat right bracket token.
3625
3626 // Don't worry about range checking the value here. That's handled by
3627 // the is*() predicates.
3628 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003629 ARM_AM::no_shift, 0, 0,
3630 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003631
3632 // If there's a pre-indexing writeback marker, '!', just add it as a token
3633 // operand.
3634 if (Parser.getTok().is(AsmToken::Exclaim)) {
3635 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3636 Parser.Lex(); // Eat the '!'.
3637 }
3638
3639 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003640 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003641
3642 // The register offset is optionally preceded by a '+' or '-'
3643 bool isNegative = false;
3644 if (Parser.getTok().is(AsmToken::Minus)) {
3645 isNegative = true;
3646 Parser.Lex(); // Eat the '-'.
3647 } else if (Parser.getTok().is(AsmToken::Plus)) {
3648 // Nothing to do.
3649 Parser.Lex(); // Eat the '+'.
3650 }
3651
3652 E = Parser.getTok().getLoc();
3653 int OffsetRegNum = tryParseRegister();
3654 if (OffsetRegNum == -1)
3655 return Error(E, "register expected");
3656
3657 // If there's a shift operator, handle it.
3658 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003659 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003660 if (Parser.getTok().is(AsmToken::Comma)) {
3661 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003662 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003663 return true;
3664 }
3665
3666 // Now we should have the closing ']'
3667 E = Parser.getTok().getLoc();
3668 if (Parser.getTok().isNot(AsmToken::RBrac))
3669 return Error(E, "']' expected");
3670 Parser.Lex(); // Eat right bracket token.
3671
3672 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003673 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003674 S, E));
3675
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003676 // If there's a pre-indexing writeback marker, '!', just add it as a token
3677 // operand.
3678 if (Parser.getTok().is(AsmToken::Exclaim)) {
3679 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3680 Parser.Lex(); // Eat the '!'.
3681 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003682
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003683 return false;
3684}
3685
Jim Grosbach7ce05792011-08-03 23:50:40 +00003686/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003687/// ( lsl | lsr | asr | ror ) , # shift_amount
3688/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003689/// return true if it parses a shift otherwise it returns false.
3690bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3691 unsigned &Amount) {
3692 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003693 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003694 if (Tok.isNot(AsmToken::Identifier))
3695 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003696 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003697 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003698 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003699 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003700 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003701 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003702 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003703 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003704 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003705 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003706 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003707 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003708 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003709 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003710
Jim Grosbach7ce05792011-08-03 23:50:40 +00003711 // rrx stands alone.
3712 Amount = 0;
3713 if (St != ARM_AM::rrx) {
3714 Loc = Parser.getTok().getLoc();
3715 // A '#' and a shift amount.
3716 const AsmToken &HashTok = Parser.getTok();
3717 if (HashTok.isNot(AsmToken::Hash))
3718 return Error(HashTok.getLoc(), "'#' expected");
3719 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003720
Jim Grosbach7ce05792011-08-03 23:50:40 +00003721 const MCExpr *Expr;
3722 if (getParser().ParseExpression(Expr))
3723 return true;
3724 // Range check the immediate.
3725 // lsl, ror: 0 <= imm <= 31
3726 // lsr, asr: 0 <= imm <= 32
3727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3728 if (!CE)
3729 return Error(Loc, "shift amount must be an immediate");
3730 int64_t Imm = CE->getValue();
3731 if (Imm < 0 ||
3732 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3733 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3734 return Error(Loc, "immediate shift value out of range");
3735 Amount = Imm;
3736 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003737
3738 return false;
3739}
3740
Jim Grosbach9d390362011-10-03 23:38:36 +00003741/// parseFPImm - A floating point immediate expression operand.
3742ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3743parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 SMLoc S = Parser.getTok().getLoc();
3745
3746 if (Parser.getTok().isNot(AsmToken::Hash))
3747 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003748
3749 // Disambiguate the VMOV forms that can accept an FP immediate.
3750 // vmov.f32 <sreg>, #imm
3751 // vmov.f64 <dreg>, #imm
3752 // vmov.f32 <dreg>, #imm @ vector f32x2
3753 // vmov.f32 <qreg>, #imm @ vector f32x4
3754 //
3755 // There are also the NEON VMOV instructions which expect an
3756 // integer constant. Make sure we don't try to parse an FPImm
3757 // for these:
3758 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3759 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3760 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3761 TyOp->getToken() != ".f64"))
3762 return MatchOperand_NoMatch;
3763
Jim Grosbach9d390362011-10-03 23:38:36 +00003764 Parser.Lex(); // Eat the '#'.
3765
3766 // Handle negation, as that still comes through as a separate token.
3767 bool isNegative = false;
3768 if (Parser.getTok().is(AsmToken::Minus)) {
3769 isNegative = true;
3770 Parser.Lex();
3771 }
3772 const AsmToken &Tok = Parser.getTok();
3773 if (Tok.is(AsmToken::Real)) {
3774 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3775 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3776 // If we had a '-' in front, toggle the sign bit.
3777 IntVal ^= (uint64_t)isNegative << 63;
3778 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3779 Parser.Lex(); // Eat the token.
3780 if (Val == -1) {
3781 TokError("floating point value out of range");
3782 return MatchOperand_ParseFail;
3783 }
3784 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3785 return MatchOperand_Success;
3786 }
3787 if (Tok.is(AsmToken::Integer)) {
3788 int64_t Val = Tok.getIntVal();
3789 Parser.Lex(); // Eat the token.
3790 if (Val > 255 || Val < 0) {
3791 TokError("encoded floating point value out of range");
3792 return MatchOperand_ParseFail;
3793 }
3794 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3795 return MatchOperand_Success;
3796 }
3797
3798 TokError("invalid floating point immediate");
3799 return MatchOperand_ParseFail;
3800}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003801/// Parse a arm instruction operand. For now this parses the operand regardless
3802/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003803bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003804 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003805 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003806
3807 // Check if the current operand has a custom associated parser, if so, try to
3808 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003809 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3810 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003811 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003812 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3813 // there was a match, but an error occurred, in which case, just return that
3814 // the operand parsing failed.
3815 if (ResTy == MatchOperand_ParseFail)
3816 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003817
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003818 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003819 default:
3820 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003821 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003822 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003823 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003824 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003825 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003826 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003827 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003828 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003829 else if (Res == -1) // irrecoverable error
3830 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003831 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3832 S = Parser.getTok().getLoc();
3833 Parser.Lex();
3834 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3835 return false;
3836 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003837
3838 // Fall though for the Identifier case that is not a register or a
3839 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003840 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003841 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003842 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003843 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003844 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003845 // This was not a register so parse other operands that start with an
3846 // identifier (like labels) as expressions and create them as immediates.
3847 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003848 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003849 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003850 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003851 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003852 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3853 return false;
3854 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003855 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003856 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003857 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003858 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003859 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003860 // #42 -> immediate.
3861 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003862 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003863 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003864 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003865 const MCExpr *ImmVal;
3866 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003867 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003869 if (CE) {
3870 int32_t Val = CE->getValue();
3871 if (isNegative && Val == 0)
3872 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003873 }
Sean Callanan76264762010-04-02 22:27:05 +00003874 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003875 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3876 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003877 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003878 case AsmToken::Colon: {
3879 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003880 // FIXME: Check it's an expression prefix,
3881 // e.g. (FOO - :lower16:BAR) isn't legal.
3882 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003883 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003884 return true;
3885
Evan Cheng75972122011-01-13 07:58:56 +00003886 const MCExpr *SubExprVal;
3887 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003888 return true;
3889
Evan Cheng75972122011-01-13 07:58:56 +00003890 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3891 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003892 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003893 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003894 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003895 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003896 }
3897}
3898
Jim Grosbach1355cf12011-07-26 17:10:22 +00003899// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003900// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003901bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003902 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003903
3904 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003905 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003906 Parser.Lex(); // Eat ':'
3907
3908 if (getLexer().isNot(AsmToken::Identifier)) {
3909 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3910 return true;
3911 }
3912
3913 StringRef IDVal = Parser.getTok().getIdentifier();
3914 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003915 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003916 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003917 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003918 } else {
3919 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3920 return true;
3921 }
3922 Parser.Lex();
3923
3924 if (getLexer().isNot(AsmToken::Colon)) {
3925 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3926 return true;
3927 }
3928 Parser.Lex(); // Eat the last ':'
3929 return false;
3930}
3931
Daniel Dunbar352e1482011-01-11 15:59:50 +00003932/// \brief Given a mnemonic, split out possible predication code and carry
3933/// setting letters to form a canonical mnemonic and flags.
3934//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003935// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003936// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003937StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003938 unsigned &PredicationCode,
3939 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003940 unsigned &ProcessorIMod,
3941 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003942 PredicationCode = ARMCC::AL;
3943 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003944 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003945
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003946 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003947 //
3948 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003949 if ((Mnemonic == "movs" && isThumb()) ||
3950 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3951 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3952 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3953 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3954 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3955 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3956 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003957 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003958
Jim Grosbach3f00e312011-07-11 17:09:57 +00003959 // First, split out any predication code. Ignore mnemonics we know aren't
3960 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003961 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003962 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003963 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003964 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003965 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3966 .Case("eq", ARMCC::EQ)
3967 .Case("ne", ARMCC::NE)
3968 .Case("hs", ARMCC::HS)
3969 .Case("cs", ARMCC::HS)
3970 .Case("lo", ARMCC::LO)
3971 .Case("cc", ARMCC::LO)
3972 .Case("mi", ARMCC::MI)
3973 .Case("pl", ARMCC::PL)
3974 .Case("vs", ARMCC::VS)
3975 .Case("vc", ARMCC::VC)
3976 .Case("hi", ARMCC::HI)
3977 .Case("ls", ARMCC::LS)
3978 .Case("ge", ARMCC::GE)
3979 .Case("lt", ARMCC::LT)
3980 .Case("gt", ARMCC::GT)
3981 .Case("le", ARMCC::LE)
3982 .Case("al", ARMCC::AL)
3983 .Default(~0U);
3984 if (CC != ~0U) {
3985 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3986 PredicationCode = CC;
3987 }
Bill Wendling52925b62010-10-29 23:50:21 +00003988 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003989
Daniel Dunbar352e1482011-01-11 15:59:50 +00003990 // Next, determine if we have a carry setting bit. We explicitly ignore all
3991 // the instructions we know end in 's'.
3992 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003993 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003994 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3995 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3996 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003997 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3998 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003999 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4000 CarrySetting = true;
4001 }
4002
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004003 // The "cps" instruction can have a interrupt mode operand which is glued into
4004 // the mnemonic. Check if this is the case, split it and parse the imod op
4005 if (Mnemonic.startswith("cps")) {
4006 // Split out any imod code.
4007 unsigned IMod =
4008 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4009 .Case("ie", ARM_PROC::IE)
4010 .Case("id", ARM_PROC::ID)
4011 .Default(~0U);
4012 if (IMod != ~0U) {
4013 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4014 ProcessorIMod = IMod;
4015 }
4016 }
4017
Jim Grosbach89df9962011-08-26 21:43:41 +00004018 // The "it" instruction has the condition mask on the end of the mnemonic.
4019 if (Mnemonic.startswith("it")) {
4020 ITMask = Mnemonic.slice(2, Mnemonic.size());
4021 Mnemonic = Mnemonic.slice(0, 2);
4022 }
4023
Daniel Dunbar352e1482011-01-11 15:59:50 +00004024 return Mnemonic;
4025}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004026
4027/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4028/// inclusion of carry set or predication code operands.
4029//
4030// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004031void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004032getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004033 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004034 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4035 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004036 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004037 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004038 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004039 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004040 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004041 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004042 Mnemonic == "mla" || Mnemonic == "smlal" ||
4043 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004044 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004045 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004046 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004047
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004048 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4049 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4050 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4051 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004052 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4053 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004054 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004055 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4056 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4057 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004058 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4059 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004060 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004061 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004062 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004063 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004064
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004065 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004066 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004067 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004068 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004069 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004070}
4071
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004072bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4073 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004074 // FIXME: This is all horribly hacky. We really need a better way to deal
4075 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004076
4077 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4078 // another does not. Specifically, the MOVW instruction does not. So we
4079 // special case it here and remove the defaulted (non-setting) cc_out
4080 // operand if that's the instruction we're trying to match.
4081 //
4082 // We do this as post-processing of the explicit operands rather than just
4083 // conditionally adding the cc_out in the first place because we need
4084 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004085 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004086 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4087 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4088 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4089 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004090
4091 // Register-register 'add' for thumb does not have a cc_out operand
4092 // when there are only two register operands.
4093 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4094 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4095 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4096 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4097 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004098 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004099 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4100 // have to check the immediate range here since Thumb2 has a variant
4101 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004102 if (((isThumb() && Mnemonic == "add") ||
4103 (isThumbTwo() && Mnemonic == "sub")) &&
4104 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004105 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4106 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4107 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004108 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4109 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4110 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004111 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004112 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4113 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004114 // selecting via the generic "add" mnemonic, so to know that we
4115 // should remove the cc_out operand, we have to explicitly check that
4116 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004117 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4118 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004119 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4120 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4121 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4122 // Nest conditions rather than one big 'if' statement for readability.
4123 //
4124 // If either register is a high reg, it's either one of the SP
4125 // variants (handled above) or a 32-bit encoding, so we just
4126 // check against T3.
4127 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4128 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4129 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4130 return false;
4131 // If both registers are low, we're in an IT block, and the immediate is
4132 // in range, we should use encoding T1 instead, which has a cc_out.
4133 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004134 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004135 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4136 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4137 return false;
4138
4139 // Otherwise, we use encoding T4, which does not have a cc_out
4140 // operand.
4141 return true;
4142 }
4143
Jim Grosbach64944f42011-09-14 21:00:40 +00004144 // The thumb2 multiply instruction doesn't have a CCOut register, so
4145 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4146 // use the 16-bit encoding or not.
4147 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4148 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4149 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4150 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4151 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4152 // If the registers aren't low regs, the destination reg isn't the
4153 // same as one of the source regs, or the cc_out operand is zero
4154 // outside of an IT block, we have to use the 32-bit encoding, so
4155 // remove the cc_out operand.
4156 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4157 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4158 !inITBlock() ||
4159 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4160 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4161 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4162 static_cast<ARMOperand*>(Operands[4])->getReg())))
4163 return true;
4164
4165
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004166
Jim Grosbachf69c8042011-08-24 21:42:27 +00004167 // Register-register 'add/sub' for thumb does not have a cc_out operand
4168 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4169 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4170 // right, this will result in better diagnostics (which operand is off)
4171 // anyway.
4172 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4173 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004174 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4175 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4176 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4177 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004178
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004179 return false;
4180}
4181
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004182static bool isDataTypeToken(StringRef Tok) {
4183 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4184 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4185 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4186 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4187 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4188 Tok == ".f" || Tok == ".d";
4189}
4190
4191// FIXME: This bit should probably be handled via an explicit match class
4192// in the .td files that matches the suffix instead of having it be
4193// a literal string token the way it is now.
4194static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4195 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4196}
4197
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004198/// Parse an arm instruction mnemonic followed by its operands.
4199bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4200 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4201 // Create the leading tokens for the mnemonic, split by '.' characters.
4202 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004203 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004204
Daniel Dunbar352e1482011-01-11 15:59:50 +00004205 // Split out the predication code and carry setting flag from the mnemonic.
4206 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004207 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004208 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004209 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004210 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004211 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004212
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004213 // In Thumb1, only the branch (B) instruction can be predicated.
4214 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4215 Parser.EatToEndOfStatement();
4216 return Error(NameLoc, "conditional execution not supported in Thumb1");
4217 }
4218
Jim Grosbachffa32252011-07-19 19:13:28 +00004219 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4220
Jim Grosbach89df9962011-08-26 21:43:41 +00004221 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4222 // is the mask as it will be for the IT encoding if the conditional
4223 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4224 // where the conditional bit0 is zero, the instruction post-processing
4225 // will adjust the mask accordingly.
4226 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004227 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4228 if (ITMask.size() > 3) {
4229 Parser.EatToEndOfStatement();
4230 return Error(Loc, "too many conditions on IT instruction");
4231 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004232 unsigned Mask = 8;
4233 for (unsigned i = ITMask.size(); i != 0; --i) {
4234 char pos = ITMask[i - 1];
4235 if (pos != 't' && pos != 'e') {
4236 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004237 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004238 }
4239 Mask >>= 1;
4240 if (ITMask[i - 1] == 't')
4241 Mask |= 8;
4242 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004243 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004244 }
4245
Jim Grosbachffa32252011-07-19 19:13:28 +00004246 // FIXME: This is all a pretty gross hack. We should automatically handle
4247 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004248
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004249 // Next, add the CCOut and ConditionCode operands, if needed.
4250 //
4251 // For mnemonics which can ever incorporate a carry setting bit or predication
4252 // code, our matching model involves us always generating CCOut and
4253 // ConditionCode operands to match the mnemonic "as written" and then we let
4254 // the matcher deal with finding the right instruction or generating an
4255 // appropriate error.
4256 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004257 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004258
Jim Grosbach33c16a22011-07-14 22:04:21 +00004259 // If we had a carry-set on an instruction that can't do that, issue an
4260 // error.
4261 if (!CanAcceptCarrySet && CarrySetting) {
4262 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004263 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004264 "' can not set flags, but 's' suffix specified");
4265 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004266 // If we had a predication code on an instruction that can't do that, issue an
4267 // error.
4268 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4269 Parser.EatToEndOfStatement();
4270 return Error(NameLoc, "instruction '" + Mnemonic +
4271 "' is not predicable, but condition code specified");
4272 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004273
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004274 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004275 if (CanAcceptCarrySet) {
4276 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004277 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004278 Loc));
4279 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004280
4281 // Add the predication code operand, if necessary.
4282 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004283 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4284 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004285 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004286 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004287 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004288
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004289 // Add the processor imod operand, if necessary.
4290 if (ProcessorIMod) {
4291 Operands.push_back(ARMOperand::CreateImm(
4292 MCConstantExpr::Create(ProcessorIMod, getContext()),
4293 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004294 }
4295
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004296 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004297 while (Next != StringRef::npos) {
4298 Start = Next;
4299 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004300 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004301
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004302 // Some NEON instructions have an optional datatype suffix that is
4303 // completely ignored. Check for that.
4304 if (isDataTypeToken(ExtraToken) &&
4305 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4306 continue;
4307
Jim Grosbach81d2e392011-09-07 16:06:04 +00004308 if (ExtraToken != ".n") {
4309 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4310 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4311 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004312 }
4313
4314 // Read the remaining operands.
4315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004316 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004317 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004318 Parser.EatToEndOfStatement();
4319 return true;
4320 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004321
4322 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004323 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004324
4325 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004326 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004327 Parser.EatToEndOfStatement();
4328 return true;
4329 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004330 }
4331 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004332
Chris Lattnercbf8a982010-09-11 16:18:25 +00004333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004334 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004335 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004336 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004337 }
Bill Wendling146018f2010-11-06 21:42:12 +00004338
Chris Lattner34e53142010-09-08 05:10:46 +00004339 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004340
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004341 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4342 // do and don't have a cc_out optional-def operand. With some spot-checks
4343 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004344 // parse and adjust accordingly before actually matching. We shouldn't ever
4345 // try to remove a cc_out operand that was explicitly set on the the
4346 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4347 // table driven matcher doesn't fit well with the ARM instruction set.
4348 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004349 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4350 Operands.erase(Operands.begin() + 1);
4351 delete Op;
4352 }
4353
Jim Grosbachcf121c32011-07-28 21:57:55 +00004354 // ARM mode 'blx' need special handling, as the register operand version
4355 // is predicable, but the label operand version is not. So, we can't rely
4356 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004357 // a k_CondCode operand in the list. If we're trying to match the label
4358 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004359 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4360 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4361 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4362 Operands.erase(Operands.begin() + 1);
4363 delete Op;
4364 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004365
4366 // The vector-compare-to-zero instructions have a literal token "#0" at
4367 // the end that comes to here as an immediate operand. Convert it to a
4368 // token to play nicely with the matcher.
4369 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4370 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4371 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4372 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4373 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4374 if (CE && CE->getValue() == 0) {
4375 Operands.erase(Operands.begin() + 5);
4376 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4377 delete Op;
4378 }
4379 }
Jim Grosbach68259142011-10-03 22:30:24 +00004380 // VCMP{E} does the same thing, but with a different operand count.
4381 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4382 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4383 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4385 if (CE && CE->getValue() == 0) {
4386 Operands.erase(Operands.begin() + 4);
4387 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4388 delete Op;
4389 }
4390 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004391 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4392 // end. Convert it to a token here.
4393 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4394 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4395 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4396 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4397 if (CE && CE->getValue() == 0) {
4398 Operands.erase(Operands.begin() + 5);
4399 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4400 delete Op;
4401 }
4402 }
4403
Chris Lattner98986712010-01-14 22:21:20 +00004404 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004405}
4406
Jim Grosbach189610f2011-07-26 18:25:39 +00004407// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004408
4409// return 'true' if register list contains non-low GPR registers,
4410// 'false' otherwise. If Reg is in the register list or is HiReg, set
4411// 'containsReg' to true.
4412static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4413 unsigned HiReg, bool &containsReg) {
4414 containsReg = false;
4415 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4416 unsigned OpReg = Inst.getOperand(i).getReg();
4417 if (OpReg == Reg)
4418 containsReg = true;
4419 // Anything other than a low register isn't legal here.
4420 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4421 return true;
4422 }
4423 return false;
4424}
4425
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004426// Check if the specified regisgter is in the register list of the inst,
4427// starting at the indicated operand number.
4428static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4429 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4430 unsigned OpReg = Inst.getOperand(i).getReg();
4431 if (OpReg == Reg)
4432 return true;
4433 }
4434 return false;
4435}
4436
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004437// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4438// the ARMInsts array) instead. Getting that here requires awkward
4439// API changes, though. Better way?
4440namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004441extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004442}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004443static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004444 return ARMInsts[Opcode];
4445}
4446
Jim Grosbach189610f2011-07-26 18:25:39 +00004447// FIXME: We would really like to be able to tablegen'erate this.
4448bool ARMAsmParser::
4449validateInstruction(MCInst &Inst,
4450 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004451 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004452 SMLoc Loc = Operands[0]->getStartLoc();
4453 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004454 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4455 // being allowed in IT blocks, but not being predicable. It just always
4456 // executes.
4457 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004458 unsigned bit = 1;
4459 if (ITState.FirstCond)
4460 ITState.FirstCond = false;
4461 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004462 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004463 // The instruction must be predicable.
4464 if (!MCID.isPredicable())
4465 return Error(Loc, "instructions in IT block must be predicable");
4466 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4467 unsigned ITCond = bit ? ITState.Cond :
4468 ARMCC::getOppositeCondition(ITState.Cond);
4469 if (Cond != ITCond) {
4470 // Find the condition code Operand to get its SMLoc information.
4471 SMLoc CondLoc;
4472 for (unsigned i = 1; i < Operands.size(); ++i)
4473 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4474 CondLoc = Operands[i]->getStartLoc();
4475 return Error(CondLoc, "incorrect condition in IT block; got '" +
4476 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4477 "', but expected '" +
4478 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4479 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004480 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004481 } else if (isThumbTwo() && MCID.isPredicable() &&
4482 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004483 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4484 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004485 return Error(Loc, "predicated instructions must be in IT block");
4486
Jim Grosbach189610f2011-07-26 18:25:39 +00004487 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004488 case ARM::LDRD:
4489 case ARM::LDRD_PRE:
4490 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004491 case ARM::LDREXD: {
4492 // Rt2 must be Rt + 1.
4493 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4494 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4495 if (Rt2 != Rt + 1)
4496 return Error(Operands[3]->getStartLoc(),
4497 "destination operands must be sequential");
4498 return false;
4499 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004500 case ARM::STRD: {
4501 // Rt2 must be Rt + 1.
4502 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4503 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4504 if (Rt2 != Rt + 1)
4505 return Error(Operands[3]->getStartLoc(),
4506 "source operands must be sequential");
4507 return false;
4508 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004509 case ARM::STRD_PRE:
4510 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004511 case ARM::STREXD: {
4512 // Rt2 must be Rt + 1.
4513 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4514 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4515 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004516 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004517 "source operands must be sequential");
4518 return false;
4519 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004520 case ARM::SBFX:
4521 case ARM::UBFX: {
4522 // width must be in range [1, 32-lsb]
4523 unsigned lsb = Inst.getOperand(2).getImm();
4524 unsigned widthm1 = Inst.getOperand(3).getImm();
4525 if (widthm1 >= 32 - lsb)
4526 return Error(Operands[5]->getStartLoc(),
4527 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004528 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004529 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004530 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004531 // If we're parsing Thumb2, the .w variant is available and handles
4532 // most cases that are normally illegal for a Thumb1 LDM
4533 // instruction. We'll make the transformation in processInstruction()
4534 // if necessary.
4535 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004536 // Thumb LDM instructions are writeback iff the base register is not
4537 // in the register list.
4538 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004539 bool hasWritebackToken =
4540 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4541 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004542 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004543 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004544 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4545 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004546 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004547 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004548 return Error(Operands[2]->getStartLoc(),
4549 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004550 // If we should not have writeback, there must not be a '!'. This is
4551 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004552 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004553 return Error(Operands[3]->getStartLoc(),
4554 "writeback operator '!' not allowed when base register "
4555 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004556
4557 break;
4558 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004559 case ARM::t2LDMIA_UPD: {
4560 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4561 return Error(Operands[4]->getStartLoc(),
4562 "writeback operator '!' not allowed when base register "
4563 "in register list");
4564 break;
4565 }
Jim Grosbach54026372011-11-10 23:17:11 +00004566 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4567 // so only issue a diagnostic for thumb1. The instructions will be
4568 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004569 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004570 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004571 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4572 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004573 return Error(Operands[2]->getStartLoc(),
4574 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004575 break;
4576 }
4577 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004578 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004579 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4580 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004581 return Error(Operands[2]->getStartLoc(),
4582 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004583 break;
4584 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004585 case ARM::tSTMIA_UPD: {
4586 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004587 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004588 return Error(Operands[4]->getStartLoc(),
4589 "registers must be in range r0-r7");
4590 break;
4591 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004592 }
4593
4594 return false;
4595}
4596
Jim Grosbach83ec8772011-11-10 23:42:14 +00004597bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004598processInstruction(MCInst &Inst,
4599 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4600 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004601 // Handle the MOV complex aliases.
Jim Grosbachee10ff82011-11-10 19:18:01 +00004602 case ARM::ASRi:
4603 case ARM::LSRi:
4604 case ARM::LSLi:
4605 case ARM::RORi: {
4606 ARM_AM::ShiftOpc ShiftTy;
4607 unsigned Amt = Inst.getOperand(2).getImm();
4608 switch(Inst.getOpcode()) {
4609 default: llvm_unreachable("unexpected opcode!");
4610 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4611 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4612 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4613 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4614 }
4615 // A shift by zero is a plain MOVr, not a MOVsi.
4616 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4617 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004618 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004619 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004620 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4621 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004622 if (Opc == ARM::MOVsi)
4623 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004624 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4625 TmpInst.addOperand(Inst.getOperand(4));
4626 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4627 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004628 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004629 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004630 case ARM::t2LDMIA_UPD: {
4631 // If this is a load of a single register, then we should use
4632 // a post-indexed LDR instruction instead, per the ARM ARM.
4633 if (Inst.getNumOperands() != 5)
4634 return false;
4635 MCInst TmpInst;
4636 TmpInst.setOpcode(ARM::t2LDR_POST);
4637 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4638 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4639 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4640 TmpInst.addOperand(MCOperand::CreateImm(4));
4641 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4642 TmpInst.addOperand(Inst.getOperand(3));
4643 Inst = TmpInst;
4644 return true;
4645 }
4646 case ARM::t2STMDB_UPD: {
4647 // If this is a store of a single register, then we should use
4648 // a pre-indexed STR instruction instead, per the ARM ARM.
4649 if (Inst.getNumOperands() != 5)
4650 return false;
4651 MCInst TmpInst;
4652 TmpInst.setOpcode(ARM::t2STR_PRE);
4653 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4654 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4655 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4656 TmpInst.addOperand(MCOperand::CreateImm(-4));
4657 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4658 TmpInst.addOperand(Inst.getOperand(3));
4659 Inst = TmpInst;
4660 return true;
4661 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004662 case ARM::LDMIA_UPD:
4663 // If this is a load of a single register via a 'pop', then we should use
4664 // a post-indexed LDR instruction instead, per the ARM ARM.
4665 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4666 Inst.getNumOperands() == 5) {
4667 MCInst TmpInst;
4668 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4669 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4670 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4671 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4672 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4673 TmpInst.addOperand(MCOperand::CreateImm(4));
4674 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4675 TmpInst.addOperand(Inst.getOperand(3));
4676 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004677 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004678 }
4679 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004680 case ARM::STMDB_UPD:
4681 // If this is a store of a single register via a 'push', then we should use
4682 // a pre-indexed STR instruction instead, per the ARM ARM.
4683 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4684 Inst.getNumOperands() == 5) {
4685 MCInst TmpInst;
4686 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4687 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4688 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4689 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4690 TmpInst.addOperand(MCOperand::CreateImm(-4));
4691 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4692 TmpInst.addOperand(Inst.getOperand(3));
4693 Inst = TmpInst;
4694 }
4695 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004696 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004697 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4698 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4699 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4700 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004701 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004702 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004703 return true;
4704 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004705 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004706 case ARM::tSUBi8:
4707 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4708 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4709 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4710 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004711 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004712 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004713 return true;
4714 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004715 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004716 case ARM::tB:
4717 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004718 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004719 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004720 return true;
4721 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004722 break;
4723 case ARM::t2B:
4724 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004725 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004726 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004727 return true;
4728 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004729 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004730 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004731 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004732 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004733 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004734 return true;
4735 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004736 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004737 case ARM::tBcc:
4738 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004739 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004740 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004741 return true;
4742 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004743 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004744 case ARM::tLDMIA: {
4745 // If the register list contains any high registers, or if the writeback
4746 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4747 // instead if we're in Thumb2. Otherwise, this should have generated
4748 // an error in validateInstruction().
4749 unsigned Rn = Inst.getOperand(0).getReg();
4750 bool hasWritebackToken =
4751 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4752 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4753 bool listContainsBase;
4754 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4755 (!listContainsBase && !hasWritebackToken) ||
4756 (listContainsBase && hasWritebackToken)) {
4757 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4758 assert (isThumbTwo());
4759 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4760 // If we're switching to the updating version, we need to insert
4761 // the writeback tied operand.
4762 if (hasWritebackToken)
4763 Inst.insert(Inst.begin(),
4764 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004765 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004766 }
4767 break;
4768 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004769 case ARM::tSTMIA_UPD: {
4770 // If the register list contains any high registers, we need to use
4771 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4772 // should have generated an error in validateInstruction().
4773 unsigned Rn = Inst.getOperand(0).getReg();
4774 bool listContainsBase;
4775 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4776 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4777 assert (isThumbTwo());
4778 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004779 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004780 }
4781 break;
4782 }
Jim Grosbach54026372011-11-10 23:17:11 +00004783 case ARM::tPOP: {
4784 bool listContainsBase;
4785 // If the register list contains any high registers, we need to use
4786 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4787 // should have generated an error in validateInstruction().
4788 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004789 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004790 assert (isThumbTwo());
4791 Inst.setOpcode(ARM::t2LDMIA_UPD);
4792 // Add the base register and writeback operands.
4793 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4794 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004795 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004796 }
4797 case ARM::tPUSH: {
4798 bool listContainsBase;
4799 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004800 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004801 assert (isThumbTwo());
4802 Inst.setOpcode(ARM::t2STMDB_UPD);
4803 // Add the base register and writeback operands.
4804 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4805 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004806 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004807 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004808 case ARM::t2MOVi: {
4809 // If we can use the 16-bit encoding and the user didn't explicitly
4810 // request the 32-bit variant, transform it here.
4811 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4812 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004813 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4814 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4815 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004816 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4817 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4818 // The operands aren't in the same order for tMOVi8...
4819 MCInst TmpInst;
4820 TmpInst.setOpcode(ARM::tMOVi8);
4821 TmpInst.addOperand(Inst.getOperand(0));
4822 TmpInst.addOperand(Inst.getOperand(4));
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 }
4831 case ARM::t2MOVr: {
4832 // If we can use the 16-bit encoding and the user didn't explicitly
4833 // request the 32-bit variant, transform it here.
4834 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4835 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4836 Inst.getOperand(2).getImm() == ARMCC::AL &&
4837 Inst.getOperand(4).getReg() == ARM::CPSR &&
4838 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4839 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4840 // The operands aren't the same for tMOV[S]r... (no cc_out)
4841 MCInst TmpInst;
4842 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4843 TmpInst.addOperand(Inst.getOperand(0));
4844 TmpInst.addOperand(Inst.getOperand(1));
4845 TmpInst.addOperand(Inst.getOperand(2));
4846 TmpInst.addOperand(Inst.getOperand(3));
4847 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004848 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004849 }
4850 break;
4851 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004852 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004853 case ARM::t2SXTB:
4854 case ARM::t2UXTH:
4855 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004856 // If we can use the 16-bit encoding and the user didn't explicitly
4857 // request the 32-bit variant, transform it here.
4858 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4859 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4860 Inst.getOperand(2).getImm() == 0 &&
4861 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4862 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004863 unsigned NewOpc;
4864 switch (Inst.getOpcode()) {
4865 default: llvm_unreachable("Illegal opcode!");
4866 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4867 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4868 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4869 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4870 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004871 // The operands aren't the same for thumb1 (no rotate operand).
4872 MCInst TmpInst;
4873 TmpInst.setOpcode(NewOpc);
4874 TmpInst.addOperand(Inst.getOperand(0));
4875 TmpInst.addOperand(Inst.getOperand(1));
4876 TmpInst.addOperand(Inst.getOperand(3));
4877 TmpInst.addOperand(Inst.getOperand(4));
4878 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004879 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00004880 }
4881 break;
4882 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004883 case ARM::t2IT: {
4884 // The mask bits for all but the first condition are represented as
4885 // the low bit of the condition code value implies 't'. We currently
4886 // always have 1 implies 't', so XOR toggle the bits if the low bit
4887 // of the condition code is zero. The encoding also expects the low
4888 // bit of the condition to be encoded as bit 4 of the mask operand,
4889 // so mask that in if needed
4890 MCOperand &MO = Inst.getOperand(1);
4891 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004892 unsigned OrigMask = Mask;
4893 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004894 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004895 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4896 for (unsigned i = 3; i != TZ; --i)
4897 Mask ^= 1 << i;
4898 } else
4899 Mask |= 0x10;
4900 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004901
4902 // Set up the IT block state according to the IT instruction we just
4903 // matched.
4904 assert(!inITBlock() && "nested IT blocks?!");
4905 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4906 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4907 ITState.CurPosition = 0;
4908 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004909 break;
4910 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004911 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00004912 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004913}
4914
Jim Grosbach47a0d522011-08-16 20:45:50 +00004915unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4916 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4917 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004918 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004919 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004920 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4921 assert(MCID.hasOptionalDef() &&
4922 "optionally flag setting instruction missing optional def operand");
4923 assert(MCID.NumOperands == Inst.getNumOperands() &&
4924 "operand count mismatch!");
4925 // Find the optional-def operand (cc_out).
4926 unsigned OpNo;
4927 for (OpNo = 0;
4928 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4929 ++OpNo)
4930 ;
4931 // If we're parsing Thumb1, reject it completely.
4932 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4933 return Match_MnemonicFail;
4934 // If we're parsing Thumb2, which form is legal depends on whether we're
4935 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004936 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4937 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004938 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004939 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4940 inITBlock())
4941 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004942 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004943 // Some high-register supporting Thumb1 encodings only allow both registers
4944 // to be from r0-r7 when in Thumb2.
4945 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4946 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4947 isARMLowRegister(Inst.getOperand(2).getReg()))
4948 return Match_RequiresThumb2;
4949 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004950 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004951 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4952 isARMLowRegister(Inst.getOperand(1).getReg()))
4953 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004954 return Match_Success;
4955}
4956
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004957bool ARMAsmParser::
4958MatchAndEmitInstruction(SMLoc IDLoc,
4959 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4960 MCStreamer &Out) {
4961 MCInst Inst;
4962 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004963 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004964 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004965 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004966 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004967 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004968 // Context sensitive operand constraints aren't handled by the matcher,
4969 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004970 if (validateInstruction(Inst, Operands)) {
4971 // Still progress the IT block, otherwise one wrong condition causes
4972 // nasty cascading errors.
4973 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004974 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004975 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004976
Jim Grosbachf8fce712011-08-11 17:35:48 +00004977 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00004978 // encoding is selected. Loop on it while changes happen so the
4979 // individual transformations can chain off each other. E.g.,
4980 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
4981 while (processInstruction(Inst, Operands))
4982 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004983
Jim Grosbacha1109882011-09-02 23:22:08 +00004984 // Only move forward at the very end so that everything in validate
4985 // and process gets a consistent answer about whether we're in an IT
4986 // block.
4987 forwardITPosition();
4988
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004989 Out.EmitInstruction(Inst);
4990 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004991 case Match_MissingFeature:
4992 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4993 return true;
4994 case Match_InvalidOperand: {
4995 SMLoc ErrorLoc = IDLoc;
4996 if (ErrorInfo != ~0U) {
4997 if (ErrorInfo >= Operands.size())
4998 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004999
Chris Lattnere73d4f82010-10-28 21:41:58 +00005000 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5001 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5002 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005003
Chris Lattnere73d4f82010-10-28 21:41:58 +00005004 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005005 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005006 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005007 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005008 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005009 // The converter function will have already emited a diagnostic.
5010 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005011 case Match_RequiresNotITBlock:
5012 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005013 case Match_RequiresITBlock:
5014 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005015 case Match_RequiresV6:
5016 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5017 case Match_RequiresThumb2:
5018 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005019 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005020
Eric Christopherc223e2b2010-10-29 09:26:59 +00005021 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005022 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005023}
5024
Jim Grosbach1355cf12011-07-26 17:10:22 +00005025/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005026bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5027 StringRef IDVal = DirectiveID.getIdentifier();
5028 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005029 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005030 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005031 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005032 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005033 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005034 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005035 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005036 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005037 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005038 return true;
5039}
5040
Jim Grosbach1355cf12011-07-26 17:10:22 +00005041/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005042/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005043bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005044 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5045 for (;;) {
5046 const MCExpr *Value;
5047 if (getParser().ParseExpression(Value))
5048 return true;
5049
Chris Lattneraaec2052010-01-19 19:46:13 +00005050 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005051
5052 if (getLexer().is(AsmToken::EndOfStatement))
5053 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005054
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005055 // FIXME: Improve diagnostic.
5056 if (getLexer().isNot(AsmToken::Comma))
5057 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005058 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005059 }
5060 }
5061
Sean Callananb9a25b72010-01-19 20:27:46 +00005062 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005063 return false;
5064}
5065
Jim Grosbach1355cf12011-07-26 17:10:22 +00005066/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005067/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005068bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005069 if (getLexer().isNot(AsmToken::EndOfStatement))
5070 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005071 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005072
5073 // TODO: set thumb mode
5074 // TODO: tell the MC streamer the mode
5075 // getParser().getStreamer().Emit???();
5076 return false;
5077}
5078
Jim Grosbach1355cf12011-07-26 17:10:22 +00005079/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005080/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005081bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005082 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5083 bool isMachO = MAI.hasSubsectionsViaSymbols();
5084 StringRef Name;
5085
5086 // Darwin asm has function name after .thumb_func direction
5087 // ELF doesn't
5088 if (isMachO) {
5089 const AsmToken &Tok = Parser.getTok();
5090 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5091 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005092 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005093 Parser.Lex(); // Consume the identifier token.
5094 }
5095
Jim Grosbachd475f862011-11-10 20:48:53 +00005096 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005097 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005098 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005099
Rafael Espindola64695402011-05-16 16:17:21 +00005100 // FIXME: assuming function name will be the line following .thumb_func
5101 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005102 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005103 }
5104
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005105 // Mark symbol as a thumb symbol.
5106 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5107 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005108 return false;
5109}
5110
Jim Grosbach1355cf12011-07-26 17:10:22 +00005111/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005112/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005113bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005114 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005115 if (Tok.isNot(AsmToken::Identifier))
5116 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005117 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005118 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005119 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005120 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005121 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005122 else
5123 return Error(L, "unrecognized syntax mode in .syntax directive");
5124
5125 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005126 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005127 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005128
5129 // TODO tell the MC streamer the mode
5130 // getParser().getStreamer().Emit???();
5131 return false;
5132}
5133
Jim Grosbach1355cf12011-07-26 17:10:22 +00005134/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005135/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005136bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005137 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005138 if (Tok.isNot(AsmToken::Integer))
5139 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005140 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005141 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005142 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005143 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005144 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005145 else
5146 return Error(L, "invalid operand to .code directive");
5147
5148 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005149 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005150 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005151
Evan Cheng32869202011-07-08 22:36:29 +00005152 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005153 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005154 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005155 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005156 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005157 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005158 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005159 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005160 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005161
Kevin Enderby515d5092009-10-15 20:48:48 +00005162 return false;
5163}
5164
Sean Callanan90b70972010-04-07 20:29:34 +00005165extern "C" void LLVMInitializeARMAsmLexer();
5166
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005167/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005168extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005169 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5170 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005171 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005172}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005173
Chris Lattner0692ee62010-09-06 19:11:01 +00005174#define GET_REGISTER_MATCHER
5175#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005176#include "ARMGenAsmMatcher.inc"