blob: ded7d50c1efe407748a35c7bcab6742a04858d81 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000048 struct {
49 ARMCC::CondCodes Cond; // Condition for IT block.
50 unsigned Mask:4; // Condition mask for instructions.
51 // Starting at first 1 (from lsb).
52 // '1' condition as indicated in IT.
53 // '0' inverse of condition (else).
54 // Count of instructions in IT block is
55 // 4 - trailingzeroes(mask)
56
57 bool FirstCond; // Explicit flag for when we're parsing the
58 // First instruction in the IT block. It's
59 // implied in the mask, so needs special
60 // handling.
61
62 unsigned CurPosition; // Current position in parsing of IT
63 // block. In range [0,3]. Initialized
64 // according to count of instructions in block.
65 // ~0U if no active IT block.
66 } ITState;
67 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000068 void forwardITPosition() {
69 if (!inITBlock()) return;
70 // Move to the next instruction in the IT block, if there is one. If not,
71 // mark the block as done.
72 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
73 if (++ITState.CurPosition == 5 - TZ)
74 ITState.CurPosition = ~0U; // Done with the IT block after this.
75 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000076
77
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000079 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
80
81 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
83
Jim Grosbach1355cf12011-07-26 17:10:22 +000084 int tryParseRegister();
85 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000086 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000088 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000089 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
90 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
92 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
94 bool parseDirectiveThumb(SMLoc L);
95 bool parseDirectiveThumbFunc(SMLoc L);
96 bool parseDirectiveCode(SMLoc L);
97 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000098
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000100 bool &CarrySetting, unsigned &ProcessorIMod,
101 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000102 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000103 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000104
Evan Chengebdeeab2011-07-08 01:53:10 +0000105 bool isThumb() const {
106 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000107 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000110 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000111 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000112 bool isThumbTwo() const {
113 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
114 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000115 bool hasV6Ops() const {
116 return STI.getFeatureBits() & ARM::HasV6Ops;
117 }
James Molloyacad68d2011-09-28 14:21:38 +0000118 bool hasV7Ops() const {
119 return STI.getFeatureBits() & ARM::HasV7Ops;
120 }
Evan Cheng32869202011-07-08 22:36:29 +0000121 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000122 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
123 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000124 }
James Molloyacad68d2011-09-28 14:21:38 +0000125 bool isMClass() const {
126 return STI.getFeatureBits() & ARM::FeatureMClass;
127 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000128
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000129 /// @name Auto-generated Match Functions
130 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000131
Chris Lattner0692ee62010-09-06 19:11:01 +0000132#define GET_ASSEMBLER_HEADER
133#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135 /// }
136
Jim Grosbach89df9962011-08-26 21:43:41 +0000137 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000140 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000142 OperandMatchResultTy parseCoprocOptionOperand(
143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000150 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
151 StringRef Op, int Low, int High);
152 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "lsl", 0, 31);
154 }
155 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
156 return parsePKHImm(O, "asr", 1, 32);
157 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000158 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000159 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000160 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000161 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000162 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000163 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000164 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000165 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000166 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000167
168 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000169 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
171 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000173 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000175 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000177 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000179 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000181 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000183 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000185 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000187 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
193 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000195 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000197 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000199 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000201 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000203 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
205 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000207 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
209 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000211
212 bool validateInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000214 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000215 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000216 bool shouldOmitCCOutOperand(StringRef Mnemonic,
217 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000218
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000219public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000220 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000221 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000223 Match_RequiresV6,
224 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000225 };
226
Evan Chengffc0e732011-07-09 05:47:46 +0000227 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000228 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000229 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000230
Evan Chengebdeeab2011-07-08 01:53:10 +0000231 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000233
234 // Not in an ITBlock to start with.
235 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000236 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000237
Jim Grosbach1355cf12011-07-26 17:10:22 +0000238 // Implementation of the MCTargetAsmParser interface:
239 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
240 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000241 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000242 bool ParseDirective(AsmToken DirectiveID);
243
Jim Grosbach47a0d522011-08-16 20:45:50 +0000244 unsigned checkTargetMatchPredicate(MCInst &Inst);
245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 bool MatchAndEmitInstruction(SMLoc IDLoc,
247 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
248 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000249};
Jim Grosbach16c74252010-10-29 14:46:02 +0000250} // end anonymous namespace
251
Chris Lattner3a697562010-10-28 17:20:03 +0000252namespace {
253
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000254/// ARMOperand - Instances of this class represent a parsed ARM machine
255/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000256class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000257 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_CondCode,
259 k_CCOut,
260 k_ITCondMask,
261 k_CoprocNum,
262 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000263 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000264 k_Immediate,
265 k_FPImmediate,
266 k_MemBarrierOpt,
267 k_Memory,
268 k_PostIndexRegister,
269 k_MSRMask,
270 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000271 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Register,
273 k_RegisterList,
274 k_DPRRegisterList,
275 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000276 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000277 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000278 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_ShiftedRegister,
280 k_ShiftedImmediate,
281 k_ShifterImmediate,
282 k_RotateImmediate,
283 k_BitfieldDescriptor,
284 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000285 } Kind;
286
Sean Callanan76264762010-04-02 22:27:05 +0000287 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000288 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000289
290 union {
291 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000292 ARMCC::CondCodes Val;
293 } CC;
294
295 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000296 unsigned Val;
297 } Cop;
298
299 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000300 unsigned Val;
301 } CoprocOption;
302
303 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000304 unsigned Mask:4;
305 } ITMask;
306
307 struct {
308 ARM_MB::MemBOpt Val;
309 } MBOpt;
310
311 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000312 ARM_PROC::IFlags Val;
313 } IFlags;
314
315 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000316 unsigned Val;
317 } MMask;
318
319 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000320 const char *Data;
321 unsigned Length;
322 } Tok;
323
324 struct {
325 unsigned RegNum;
326 } Reg;
327
Jim Grosbach862019c2011-10-18 23:02:30 +0000328 // A vector register list is a sequential list of 1 to 4 registers.
329 struct {
330 unsigned RegNum;
331 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000332 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000333 } VectorList;
334
Bill Wendling8155e5b2010-11-06 22:19:43 +0000335 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000336 unsigned Val;
337 } VectorIndex;
338
339 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000340 const MCExpr *Val;
341 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000342
Jim Grosbach9d390362011-10-03 23:38:36 +0000343 struct {
344 unsigned Val; // encoded 8-bit representation
345 } FPImm;
346
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000347 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000348 struct {
349 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000350 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
351 // was specified.
352 const MCConstantExpr *OffsetImm; // Offset immediate value
353 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
354 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000355 unsigned ShiftImm; // shift for OffsetReg.
356 unsigned Alignment; // 0 = no alignment specified
357 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000358 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000359 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000360
361 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000363 bool isAdd;
364 ARM_AM::ShiftOpc ShiftTy;
365 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 } PostIdxReg;
367
368 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000369 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000370 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000371 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftReg;
376 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000377 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000378 struct {
379 ARM_AM::ShiftOpc ShiftTy;
380 unsigned SrcReg;
381 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000382 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000383 struct {
384 unsigned Imm;
385 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000386 struct {
387 unsigned LSB;
388 unsigned Width;
389 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000390 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000391
Bill Wendling146018f2010-11-06 21:42:12 +0000392 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
393public:
Sean Callanan76264762010-04-02 22:27:05 +0000394 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
395 Kind = o.Kind;
396 StartLoc = o.StartLoc;
397 EndLoc = o.EndLoc;
398 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000400 CC = o.CC;
401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000403 ITMask = o.ITMask;
404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000405 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000406 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000407 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CCOut:
409 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000410 Reg = o.Reg;
411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_RegisterList:
413 case k_DPRRegisterList:
414 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000415 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000416 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000417 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000418 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000419 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000420 VectorList = o.VectorList;
421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_CoprocNum:
423 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000424 Cop = o.Cop;
425 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000426 case k_CoprocOption:
427 CoprocOption = o.CoprocOption;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000430 Imm = o.Imm;
431 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000432 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000433 FPImm = o.FPImm;
434 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000435 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000436 MBOpt = o.MBOpt;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000439 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000442 PostIdxReg = o.PostIdxReg;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000445 MMask = o.MMask;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000448 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000451 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000454 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000457 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000460 RotImm = o.RotImm;
461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000463 Bitfield = o.Bitfield;
464 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000465 case k_VectorIndex:
466 VectorIndex = o.VectorIndex;
467 break;
Sean Callanan76264762010-04-02 22:27:05 +0000468 }
469 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000470
Sean Callanan76264762010-04-02 22:27:05 +0000471 /// getStartLoc - Get the location of the first token of this operand.
472 SMLoc getStartLoc() const { return StartLoc; }
473 /// getEndLoc - Get the location of the last token of this operand.
474 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475
Daniel Dunbar8462b302010-08-11 06:36:53 +0000476 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000478 return CC.Val;
479 }
480
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000481 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000483 return Cop.Val;
484 }
485
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000488 return StringRef(Tok.Data, Tok.Length);
489 }
490
491 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000493 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000494 }
495
Bill Wendling5fa22a12010-11-09 23:28:44 +0000496 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
498 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000499 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000500 }
501
Kevin Enderbycfe07242009-10-13 22:19:02 +0000502 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000504 return Imm.Val;
505 }
506
Jim Grosbach9d390362011-10-03 23:38:36 +0000507 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000508 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000509 return FPImm.Val;
510 }
511
Jim Grosbach460a9052011-10-07 23:56:00 +0000512 unsigned getVectorIndex() const {
513 assert(Kind == k_VectorIndex && "Invalid access!");
514 return VectorIndex.Val;
515 }
516
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000517 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000518 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000519 return MBOpt.Val;
520 }
521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000522 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000523 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000524 return IFlags.Val;
525 }
526
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000527 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000529 return MMask.Val;
530 }
531
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 bool isCoprocNum() const { return Kind == k_CoprocNum; }
533 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000534 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 bool isCondCode() const { return Kind == k_CondCode; }
536 bool isCCOut() const { return Kind == k_CCOut; }
537 bool isITMask() const { return Kind == k_ITCondMask; }
538 bool isITCondCode() const { return Kind == k_CondCode; }
539 bool isImm() const { return Kind == k_Immediate; }
540 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000541 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
548 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000549 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
556 }
557 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
564 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000565 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 256;
572 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000573 bool isImm0_1() const {
574 if (Kind != k_Immediate)
575 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 < 2;
580 }
581 bool isImm0_3() const {
582 if (Kind != k_Immediate)
583 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 < 4;
588 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000589 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +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 < 8;
596 }
597 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +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 < 16;
604 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000605 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 32;
612 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000613 bool isImm8() const {
614 if (Kind != k_Immediate)
615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value == 8;
620 }
621 bool isImm16() const {
622 if (Kind != k_Immediate)
623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value == 16;
628 }
629 bool isImm32() const {
630 if (Kind != k_Immediate)
631 return false;
632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
633 if (!CE) return false;
634 int64_t Value = CE->getValue();
635 return Value == 32;
636 }
637 bool isImm1_7() const {
638 if (Kind != k_Immediate)
639 return false;
640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return Value > 0 && Value < 8;
644 }
645 bool isImm1_15() const {
646 if (Kind != k_Immediate)
647 return false;
648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
649 if (!CE) return false;
650 int64_t Value = CE->getValue();
651 return Value > 0 && Value < 16;
652 }
653 bool isImm1_31() const {
654 if (Kind != k_Immediate)
655 return false;
656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value > 0 && Value < 32;
660 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000661 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000662 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000663 return false;
664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value < 17;
668 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000669 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000670 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000671 return false;
672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
673 if (!CE) return false;
674 int64_t Value = CE->getValue();
675 return Value > 0 && Value < 33;
676 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000677 bool isImm0_32() const {
678 if (Kind != k_Immediate)
679 return false;
680 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
681 if (!CE) return false;
682 int64_t Value = CE->getValue();
683 return Value >= 0 && Value < 33;
684 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000685 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000686 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000687 return false;
688 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
689 if (!CE) return false;
690 int64_t Value = CE->getValue();
691 return Value >= 0 && Value < 65536;
692 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000693 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000694 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000695 return false;
696 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
697 // If it's not a constant expression, it'll generate a fixup and be
698 // handled later.
699 if (!CE) return true;
700 int64_t Value = CE->getValue();
701 return Value >= 0 && Value < 65536;
702 }
Jim Grosbached838482011-07-26 16:24:27 +0000703 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000704 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000705 return false;
706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value >= 0 && Value <= 0xffffff;
710 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000711 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000712 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000713 return false;
714 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
715 if (!CE) return false;
716 int64_t Value = CE->getValue();
717 return Value > 0 && Value < 33;
718 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000719 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000720 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000721 return false;
722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Value = CE->getValue();
725 return Value >= 0 && Value < 32;
726 }
727 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000728 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000729 return false;
730 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
731 if (!CE) return false;
732 int64_t Value = CE->getValue();
733 return Value > 0 && Value <= 32;
734 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000735 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000736 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000737 return false;
738 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
739 if (!CE) return false;
740 int64_t Value = CE->getValue();
741 return ARM_AM::getSOImmVal(Value) != -1;
742 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000743 bool isARMSOImmNot() const {
744 if (Kind != k_Immediate)
745 return false;
746 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
747 if (!CE) return false;
748 int64_t Value = CE->getValue();
749 return ARM_AM::getSOImmVal(~Value) != -1;
750 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000751 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000752 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000753 return false;
754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return ARM_AM::getT2SOImmVal(Value) != -1;
758 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000759 bool isT2SOImmNot() const {
760 if (Kind != k_Immediate)
761 return false;
762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
763 if (!CE) return false;
764 int64_t Value = CE->getValue();
765 return ARM_AM::getT2SOImmVal(~Value) != -1;
766 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000767 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000768 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000769 return false;
770 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
771 if (!CE) return false;
772 int64_t Value = CE->getValue();
773 return Value == 1 || Value == 0;
774 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000775 bool isReg() const { return Kind == k_Register; }
776 bool isRegList() const { return Kind == k_RegisterList; }
777 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
778 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
779 bool isToken() const { return Kind == k_Token; }
780 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
781 bool isMemory() const { return Kind == k_Memory; }
782 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
783 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
784 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
785 bool isRotImm() const { return Kind == k_RotateImmediate; }
786 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
787 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000788 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000789 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000790 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000791 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000792 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000793 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000794 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000795 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
796 (alignOK || Memory.Alignment == 0);
797 }
798 bool isAlignedMemory() const {
799 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000800 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000801 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000802 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000803 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000804 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000805 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000806 if (!Memory.OffsetImm) return true;
807 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000808 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000809 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000810 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000811 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000812 return false;
813 // Immediate offset in range [-4095, 4095].
814 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
815 if (!CE) return false;
816 int64_t Val = CE->getValue();
817 return Val > -4096 && Val < 4096;
818 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000819 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000820 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000821 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000822 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000823 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000825 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000826 if (!Memory.OffsetImm) return true;
827 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000828 return Val > -256 && Val < 256;
829 }
830 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000831 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000832 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000833 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000834 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
835 // Immediate offset in range [-255, 255].
836 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
837 if (!CE) return false;
838 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000839 // Special case, #-0 is INT32_MIN.
840 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000841 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000842 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000843 // If we have an immediate that's not a constant, treat it as a label
844 // reference needing a fixup. If it is a constant, it's something else
845 // and we reject it.
846 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
847 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000849 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000850 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000851 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000852 if (!Memory.OffsetImm) return true;
853 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000854 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000855 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000856 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000857 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000858 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000860 return false;
861 return true;
862 }
863 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000864 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000865 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
866 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000867 return false;
868 return true;
869 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000871 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000872 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000873 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000874 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000875 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
877 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000878 return false;
879 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000880 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000881 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000882 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000883 return false;
884 return true;
885 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000886 bool isMemThumbRR() const {
887 // Thumb reg+reg addressing is simple. Just two registers, a base and
888 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000889 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000891 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 return isARMLowRegister(Memory.BaseRegNum) &&
893 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000894 }
895 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000897 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000898 return false;
899 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000900 if (!Memory.OffsetImm) return true;
901 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000902 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
903 }
Jim Grosbach38466302011-08-19 18:55:51 +0000904 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000905 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000906 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000907 return false;
908 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!Memory.OffsetImm) return true;
910 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000911 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
912 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000913 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000915 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000916 return false;
917 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000918 if (!Memory.OffsetImm) return true;
919 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000920 return Val >= 0 && Val <= 31;
921 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000922 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000923 if (!isMemory() || Memory.OffsetRegNum != 0 ||
924 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000925 return false;
926 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000927 if (!Memory.OffsetImm) return true;
928 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000929 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000930 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000931 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000932 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000933 return false;
934 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000935 if (!Memory.OffsetImm) return true;
936 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000937 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
938 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000939 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000940 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000941 return false;
942 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 if (!Memory.OffsetImm) return true;
944 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000945 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
946 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000947 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000949 return false;
950 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000953 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000954 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000955 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000957 return false;
958 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!Memory.OffsetImm) return true;
960 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000961 return Val >= 0 && Val < 256;
962 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000963 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000964 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000965 return false;
966 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000967 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000968 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000969 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000970 }
971 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000972 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000973 return false;
974 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!Memory.OffsetImm) return true;
976 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000977 return (Val >= 0 && Val < 4096);
978 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000979 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000980 // If we have an immediate that's not a constant, treat it as a label
981 // reference needing a fixup. If it is a constant, it's something else
982 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000983 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000984 return true;
985
Jim Grosbach57dcb852011-10-11 17:29:55 +0000986 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000987 return false;
988 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000991 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000992 }
993 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000994 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000995 return false;
996 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
997 if (!CE) return false;
998 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000999 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001000 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001001 bool isPostIdxImm8s4() const {
1002 if (Kind != k_Immediate)
1003 return false;
1004 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1005 if (!CE) return false;
1006 int64_t Val = CE->getValue();
1007 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1008 (Val == INT32_MIN);
1009 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001010
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001011 bool isMSRMask() const { return Kind == k_MSRMask; }
1012 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001013
Jim Grosbach0e387b22011-10-17 22:26:03 +00001014 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001015 bool isVecListOneD() const {
1016 if (Kind != k_VectorList) return false;
1017 return VectorList.Count == 1;
1018 }
1019
Jim Grosbach280dfad2011-10-21 18:54:25 +00001020 bool isVecListTwoD() const {
1021 if (Kind != k_VectorList) return false;
1022 return VectorList.Count == 2;
1023 }
1024
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001025 bool isVecListThreeD() const {
1026 if (Kind != k_VectorList) return false;
1027 return VectorList.Count == 3;
1028 }
1029
Jim Grosbachb6310312011-10-21 20:35:01 +00001030 bool isVecListFourD() const {
1031 if (Kind != k_VectorList) return false;
1032 return VectorList.Count == 4;
1033 }
1034
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001035 bool isVecListTwoQ() const {
1036 if (Kind != k_VectorList) return false;
1037 //FIXME: We haven't taught the parser to handle by-two register lists
1038 // yet, so don't pretend to know one.
1039 return VectorList.Count == 2 && false;
1040 }
1041
Jim Grosbach98b05a52011-11-30 01:09:44 +00001042 bool isVecListOneDAllLanes() const {
1043 if (Kind != k_VectorListAllLanes) return false;
1044 return VectorList.Count == 1;
1045 }
1046
Jim Grosbach13af2222011-11-30 18:21:25 +00001047 bool isVecListTwoDAllLanes() const {
1048 if (Kind != k_VectorListAllLanes) return false;
1049 return VectorList.Count == 2;
1050 }
1051
Jim Grosbach7636bf62011-12-02 00:35:16 +00001052 bool isVecListOneDByteIndexed() const {
1053 if (Kind != k_VectorListIndexed) return false;
1054 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1055 }
1056
Jim Grosbach460a9052011-10-07 23:56:00 +00001057 bool isVectorIndex8() const {
1058 if (Kind != k_VectorIndex) return false;
1059 return VectorIndex.Val < 8;
1060 }
1061 bool isVectorIndex16() const {
1062 if (Kind != k_VectorIndex) return false;
1063 return VectorIndex.Val < 4;
1064 }
1065 bool isVectorIndex32() const {
1066 if (Kind != k_VectorIndex) return false;
1067 return VectorIndex.Val < 2;
1068 }
1069
Jim Grosbach0e387b22011-10-17 22:26:03 +00001070 bool isNEONi8splat() const {
1071 if (Kind != k_Immediate)
1072 return false;
1073 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1074 // Must be a constant.
1075 if (!CE) return false;
1076 int64_t Value = CE->getValue();
1077 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1078 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001079 return Value >= 0 && Value < 256;
1080 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001081
Jim Grosbachea461102011-10-17 23:09:09 +00001082 bool isNEONi16splat() const {
1083 if (Kind != k_Immediate)
1084 return false;
1085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1086 // Must be a constant.
1087 if (!CE) return false;
1088 int64_t Value = CE->getValue();
1089 // i16 value in the range [0,255] or [0x0100, 0xff00]
1090 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1091 }
1092
Jim Grosbach6248a542011-10-18 00:22:00 +00001093 bool isNEONi32splat() const {
1094 if (Kind != k_Immediate)
1095 return false;
1096 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1097 // Must be a constant.
1098 if (!CE) return false;
1099 int64_t Value = CE->getValue();
1100 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1101 return (Value >= 0 && Value < 256) ||
1102 (Value >= 0x0100 && Value <= 0xff00) ||
1103 (Value >= 0x010000 && Value <= 0xff0000) ||
1104 (Value >= 0x01000000 && Value <= 0xff000000);
1105 }
1106
1107 bool isNEONi32vmov() const {
1108 if (Kind != k_Immediate)
1109 return false;
1110 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1111 // Must be a constant.
1112 if (!CE) return false;
1113 int64_t Value = CE->getValue();
1114 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1115 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1116 return (Value >= 0 && Value < 256) ||
1117 (Value >= 0x0100 && Value <= 0xff00) ||
1118 (Value >= 0x010000 && Value <= 0xff0000) ||
1119 (Value >= 0x01000000 && Value <= 0xff000000) ||
1120 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1121 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1122 }
1123
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001124 bool isNEONi64splat() const {
1125 if (Kind != k_Immediate)
1126 return false;
1127 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1128 // Must be a constant.
1129 if (!CE) return false;
1130 uint64_t Value = CE->getValue();
1131 // i64 value with each byte being either 0 or 0xff.
1132 for (unsigned i = 0; i < 8; ++i)
1133 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1134 return true;
1135 }
1136
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001137 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001138 // Add as immediates when possible. Null MCExpr = 0.
1139 if (Expr == 0)
1140 Inst.addOperand(MCOperand::CreateImm(0));
1141 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001142 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1143 else
1144 Inst.addOperand(MCOperand::CreateExpr(Expr));
1145 }
1146
Daniel Dunbar8462b302010-08-11 06:36:53 +00001147 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001148 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001149 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001150 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1151 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001152 }
1153
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001154 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1157 }
1158
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001159 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
1161 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1162 }
1163
1164 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1167 }
1168
Jim Grosbach89df9962011-08-26 21:43:41 +00001169 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
1171 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1172 }
1173
1174 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
1176 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1177 }
1178
Jim Grosbachd67641b2010-12-06 18:21:12 +00001179 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
1181 Inst.addOperand(MCOperand::CreateReg(getReg()));
1182 }
1183
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001184 void addRegOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 Inst.addOperand(MCOperand::CreateReg(getReg()));
1187 }
1188
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001189 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001190 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001191 assert(isRegShiftedReg() &&
1192 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001193 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1194 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001195 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001196 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001197 }
1198
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001199 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001200 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001201 assert(isRegShiftedImm() &&
1202 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001203 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001204 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001205 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001206 }
1207
Jim Grosbach580f4a92011-07-25 22:20:28 +00001208 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001209 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001210 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1211 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001212 }
1213
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001214 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001215 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001216 const SmallVectorImpl<unsigned> &RegList = getRegList();
1217 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001218 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1219 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001220 }
1221
Bill Wendling0f630752010-11-17 04:32:08 +00001222 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1223 addRegListOperands(Inst, N);
1224 }
1225
1226 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1227 addRegListOperands(Inst, N);
1228 }
1229
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001230 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1233 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1234 }
1235
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001236 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 // Munge the lsb/width into a bitfield mask.
1239 unsigned lsb = Bitfield.LSB;
1240 unsigned width = Bitfield.Width;
1241 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1242 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1243 (32 - (lsb + width)));
1244 Inst.addOperand(MCOperand::CreateImm(Mask));
1245 }
1246
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001247 void addImmOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
1249 addExpr(Inst, getImm());
1250 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001251
Jim Grosbach9d390362011-10-03 23:38:36 +00001252 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 1 && "Invalid number of operands!");
1254 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1255 }
1256
Jim Grosbacha77295d2011-09-08 22:07:06 +00001257 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
1259 // FIXME: We really want to scale the value here, but the LDRD/STRD
1260 // instruction don't encode operands that way yet.
1261 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1262 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1263 }
1264
Jim Grosbach72f39f82011-08-24 21:22:15 +00001265 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
1267 // The immediate is scaled by four in the encoding and is stored
1268 // in the MCInst as such. Lop off the low two bits here.
1269 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1270 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1271 }
1272
1273 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
1275 // The immediate is scaled by four in the encoding and is stored
1276 // in the MCInst as such. Lop off the low two bits here.
1277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1278 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1279 }
1280
Jim Grosbachf4943352011-07-25 23:09:14 +00001281 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 // The constant encodes as the immediate-1, and we store in the instruction
1284 // the bits as encoded, so subtract off one here.
1285 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1286 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1287 }
1288
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001289 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
1291 // The constant encodes as the immediate-1, and we store in the instruction
1292 // the bits as encoded, so subtract off one here.
1293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1294 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1295 }
1296
Jim Grosbach70939ee2011-08-17 21:51:27 +00001297 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 // The constant encodes as the immediate, except for 32, which encodes as
1300 // zero.
1301 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1302 unsigned Imm = CE->getValue();
1303 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1304 }
1305
Jim Grosbachf6c05252011-07-21 17:23:04 +00001306 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1309 // the instruction as well.
1310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1311 int Val = CE->getValue();
1312 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1313 }
1314
Jim Grosbach89a63372011-10-28 22:36:30 +00001315 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
1317 // The operand is actually a t2_so_imm, but we have its bitwise
1318 // negation in the assembly source, so twiddle it here.
1319 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1320 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1321 }
1322
Jim Grosbache70ec842011-10-28 22:50:54 +00001323 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 // The operand is actually a so_imm, but we have its bitwise
1326 // negation in the assembly source, so twiddle it here.
1327 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1328 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1329 }
1330
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001331 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
1333 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1334 }
1335
Jim Grosbach7ce05792011-08-03 23:50:40 +00001336 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001338 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001339 }
1340
Jim Grosbach57dcb852011-10-11 17:29:55 +00001341 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1342 assert(N == 2 && "Invalid number of operands!");
1343 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1344 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1345 }
1346
Jim Grosbach7ce05792011-08-03 23:50:40 +00001347 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1348 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001349 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1350 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001351 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1352 // Special case for #-0
1353 if (Val == INT32_MIN) Val = 0;
1354 if (Val < 0) Val = -Val;
1355 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1356 } else {
1357 // For register offset, we encode the shift type and negation flag
1358 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001359 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1360 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001361 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001362 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1363 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001364 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001365 }
1366
Jim Grosbach039c2e12011-08-04 23:01:30 +00001367 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1368 assert(N == 2 && "Invalid number of operands!");
1369 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1370 assert(CE && "non-constant AM2OffsetImm operand!");
1371 int32_t Val = CE->getValue();
1372 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1373 // Special case for #-0
1374 if (Val == INT32_MIN) Val = 0;
1375 if (Val < 0) Val = -Val;
1376 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1377 Inst.addOperand(MCOperand::CreateReg(0));
1378 Inst.addOperand(MCOperand::CreateImm(Val));
1379 }
1380
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001381 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001383 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1384 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001385 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1386 // Special case for #-0
1387 if (Val == INT32_MIN) Val = 0;
1388 if (Val < 0) Val = -Val;
1389 Val = ARM_AM::getAM3Opc(AddSub, Val);
1390 } else {
1391 // For register offset, we encode the shift type and negation flag
1392 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001393 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001394 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001395 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1396 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
1398 }
1399
1400 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001402 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001403 int32_t Val =
1404 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1405 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1406 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001407 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001408 }
1409
1410 // Constant offset.
1411 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1412 int32_t Val = CE->getValue();
1413 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1414 // Special case for #-0
1415 if (Val == INT32_MIN) Val = 0;
1416 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001417 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001418 Inst.addOperand(MCOperand::CreateReg(0));
1419 Inst.addOperand(MCOperand::CreateImm(Val));
1420 }
1421
Jim Grosbach7ce05792011-08-03 23:50:40 +00001422 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1423 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001424 // If we have an immediate that's not a constant, treat it as a label
1425 // reference needing a fixup. If it is a constant, it's something else
1426 // and we reject it.
1427 if (isImm()) {
1428 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1429 Inst.addOperand(MCOperand::CreateImm(0));
1430 return;
1431 }
1432
Jim Grosbach7ce05792011-08-03 23:50:40 +00001433 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001435 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1436 // Special case for #-0
1437 if (Val == INT32_MIN) Val = 0;
1438 if (Val < 0) Val = -Val;
1439 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001440 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001441 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001442 }
1443
Jim Grosbacha77295d2011-09-08 22:07:06 +00001444 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001446 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1447 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001448 Inst.addOperand(MCOperand::CreateImm(Val));
1449 }
1450
Jim Grosbachb6aed502011-09-09 18:37:27 +00001451 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 2 && "Invalid number of operands!");
1453 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001454 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1455 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001456 Inst.addOperand(MCOperand::CreateImm(Val));
1457 }
1458
Jim Grosbach7ce05792011-08-03 23:50:40 +00001459 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001461 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1462 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001464 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001465
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001466 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1467 addMemImm8OffsetOperands(Inst, N);
1468 }
1469
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001470 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001471 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001472 }
1473
1474 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 2 && "Invalid number of operands!");
1476 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001477 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001478 addExpr(Inst, getImm());
1479 Inst.addOperand(MCOperand::CreateImm(0));
1480 return;
1481 }
1482
1483 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001484 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1485 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001486 Inst.addOperand(MCOperand::CreateImm(Val));
1487 }
1488
Jim Grosbach7ce05792011-08-03 23:50:40 +00001489 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001491 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001492 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001493 addExpr(Inst, getImm());
1494 Inst.addOperand(MCOperand::CreateImm(0));
1495 return;
1496 }
1497
1498 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001499 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1500 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001501 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001502 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001503
Jim Grosbach7f739be2011-09-19 22:21:13 +00001504 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001506 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1507 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001508 }
1509
1510 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001512 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1513 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001514 }
1515
Jim Grosbach7ce05792011-08-03 23:50:40 +00001516 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001518 unsigned Val =
1519 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1520 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001521 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1522 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001523 Inst.addOperand(MCOperand::CreateImm(Val));
1524 }
1525
Jim Grosbachab899c12011-09-07 23:10:15 +00001526 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001528 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1529 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1530 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001531 }
1532
Jim Grosbach7ce05792011-08-03 23:50:40 +00001533 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001535 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1536 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001537 }
1538
Jim Grosbach60f91a32011-08-19 17:55:24 +00001539 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1540 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001541 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1542 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001543 Inst.addOperand(MCOperand::CreateImm(Val));
1544 }
1545
Jim Grosbach38466302011-08-19 18:55:51 +00001546 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1547 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001548 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1549 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001550 Inst.addOperand(MCOperand::CreateImm(Val));
1551 }
1552
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001553 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1554 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001555 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1556 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001557 Inst.addOperand(MCOperand::CreateImm(Val));
1558 }
1559
Jim Grosbachecd85892011-08-19 18:13:48 +00001560 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001562 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1563 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001564 Inst.addOperand(MCOperand::CreateImm(Val));
1565 }
1566
Jim Grosbach7ce05792011-08-03 23:50:40 +00001567 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1568 assert(N == 1 && "Invalid number of operands!");
1569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1570 assert(CE && "non-constant post-idx-imm8 operand!");
1571 int Imm = CE->getValue();
1572 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001573 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001574 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1575 Inst.addOperand(MCOperand::CreateImm(Imm));
1576 }
1577
Jim Grosbach2bd01182011-10-11 21:55:36 +00001578 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1581 assert(CE && "non-constant post-idx-imm8s4 operand!");
1582 int Imm = CE->getValue();
1583 bool isAdd = Imm >= 0;
1584 if (Imm == INT32_MIN) Imm = 0;
1585 // Immediate is scaled by 4.
1586 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1587 Inst.addOperand(MCOperand::CreateImm(Imm));
1588 }
1589
Jim Grosbach7ce05792011-08-03 23:50:40 +00001590 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 2 && "Invalid number of operands!");
1592 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001593 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1594 }
1595
1596 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1597 assert(N == 2 && "Invalid number of operands!");
1598 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1599 // The sign, shift type, and shift amount are encoded in a single operand
1600 // using the AM2 encoding helpers.
1601 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1602 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1603 PostIdxReg.ShiftTy);
1604 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001605 }
1606
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001607 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
1609 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1610 }
1611
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001612 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1615 }
1616
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001617 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001618 assert(N == 1 && "Invalid number of operands!");
1619 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1620 }
1621
Jim Grosbach7636bf62011-12-02 00:35:16 +00001622 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 2 && "Invalid number of operands!");
1624 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1625 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1626 }
1627
Jim Grosbach460a9052011-10-07 23:56:00 +00001628 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1629 assert(N == 1 && "Invalid number of operands!");
1630 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1631 }
1632
1633 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1634 assert(N == 1 && "Invalid number of operands!");
1635 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1636 }
1637
1638 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1639 assert(N == 1 && "Invalid number of operands!");
1640 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1641 }
1642
Jim Grosbach0e387b22011-10-17 22:26:03 +00001643 void addNEONi8splatOperands(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 // Mask in that this is an i8 splat.
1647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1648 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1649 }
1650
Jim Grosbachea461102011-10-17 23:09:09 +00001651 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1652 assert(N == 1 && "Invalid number of operands!");
1653 // The immediate encodes the type of constant as well as the value.
1654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1655 unsigned Value = CE->getValue();
1656 if (Value >= 256)
1657 Value = (Value >> 8) | 0xa00;
1658 else
1659 Value |= 0x800;
1660 Inst.addOperand(MCOperand::CreateImm(Value));
1661 }
1662
Jim Grosbach6248a542011-10-18 00:22:00 +00001663 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 1 && "Invalid number of operands!");
1665 // The immediate encodes the type of constant as well as the value.
1666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1667 unsigned Value = CE->getValue();
1668 if (Value >= 256 && Value <= 0xff00)
1669 Value = (Value >> 8) | 0x200;
1670 else if (Value > 0xffff && Value <= 0xff0000)
1671 Value = (Value >> 16) | 0x400;
1672 else if (Value > 0xffffff)
1673 Value = (Value >> 24) | 0x600;
1674 Inst.addOperand(MCOperand::CreateImm(Value));
1675 }
1676
1677 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1678 assert(N == 1 && "Invalid number of operands!");
1679 // The immediate encodes the type of constant as well as the value.
1680 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1681 unsigned Value = CE->getValue();
1682 if (Value >= 256 && Value <= 0xffff)
1683 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1684 else if (Value > 0xffff && Value <= 0xffffff)
1685 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1686 else if (Value > 0xffffff)
1687 Value = (Value >> 24) | 0x600;
1688 Inst.addOperand(MCOperand::CreateImm(Value));
1689 }
1690
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001691 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 1 && "Invalid number of operands!");
1693 // The immediate encodes the type of constant as well as the value.
1694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1695 uint64_t Value = CE->getValue();
1696 unsigned Imm = 0;
1697 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1698 Imm |= (Value & 1) << i;
1699 }
1700 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1701 }
1702
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001703 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001704
Jim Grosbach89df9962011-08-26 21:43:41 +00001705 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001706 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001707 Op->ITMask.Mask = Mask;
1708 Op->StartLoc = S;
1709 Op->EndLoc = S;
1710 return Op;
1711 }
1712
Chris Lattner3a697562010-10-28 17:20:03 +00001713 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001714 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001715 Op->CC.Val = CC;
1716 Op->StartLoc = S;
1717 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001718 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001719 }
1720
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001721 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001722 ARMOperand *Op = new ARMOperand(k_CoprocNum);
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
1729 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001730 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001731 Op->Cop.Val = CopVal;
1732 Op->StartLoc = S;
1733 Op->EndLoc = S;
1734 return Op;
1735 }
1736
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001737 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1738 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1739 Op->Cop.Val = Val;
1740 Op->StartLoc = S;
1741 Op->EndLoc = E;
1742 return Op;
1743 }
1744
Jim Grosbachd67641b2010-12-06 18:21:12 +00001745 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001747 Op->Reg.RegNum = RegNum;
1748 Op->StartLoc = S;
1749 Op->EndLoc = S;
1750 return Op;
1751 }
1752
Chris Lattner3a697562010-10-28 17:20:03 +00001753 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001755 Op->Tok.Data = Str.data();
1756 Op->Tok.Length = Str.size();
1757 Op->StartLoc = S;
1758 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001759 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001760 }
1761
Bill Wendling50d0f582010-11-18 23:43:05 +00001762 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001763 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001764 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001765 Op->StartLoc = S;
1766 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001767 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001768 }
1769
Jim Grosbache8606dc2011-07-13 17:50:29 +00001770 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1771 unsigned SrcReg,
1772 unsigned ShiftReg,
1773 unsigned ShiftImm,
1774 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001775 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001776 Op->RegShiftedReg.ShiftTy = ShTy;
1777 Op->RegShiftedReg.SrcReg = SrcReg;
1778 Op->RegShiftedReg.ShiftReg = ShiftReg;
1779 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001780 Op->StartLoc = S;
1781 Op->EndLoc = E;
1782 return Op;
1783 }
1784
Owen Anderson92a20222011-07-21 18:54:16 +00001785 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1786 unsigned SrcReg,
1787 unsigned ShiftImm,
1788 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001789 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001790 Op->RegShiftedImm.ShiftTy = ShTy;
1791 Op->RegShiftedImm.SrcReg = SrcReg;
1792 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Jim Grosbach580f4a92011-07-25 22:20:28 +00001798 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001799 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001800 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001801 Op->ShifterImm.isASR = isASR;
1802 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001803 Op->StartLoc = S;
1804 Op->EndLoc = E;
1805 return Op;
1806 }
1807
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001808 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001809 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001810 Op->RotImm.Imm = Imm;
1811 Op->StartLoc = S;
1812 Op->EndLoc = E;
1813 return Op;
1814 }
1815
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001816 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1817 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001818 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001819 Op->Bitfield.LSB = LSB;
1820 Op->Bitfield.Width = Width;
1821 Op->StartLoc = S;
1822 Op->EndLoc = E;
1823 return Op;
1824 }
1825
Bill Wendling7729e062010-11-09 22:44:22 +00001826 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001827 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001828 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001829 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001830
Jim Grosbachd300b942011-09-13 22:56:44 +00001831 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001832 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001833 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001834 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001835 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001836
1837 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001838 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001839 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001840 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001841 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001842 Op->StartLoc = StartLoc;
1843 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001844 return Op;
1845 }
1846
Jim Grosbach862019c2011-10-18 23:02:30 +00001847 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1848 SMLoc S, SMLoc E) {
1849 ARMOperand *Op = new ARMOperand(k_VectorList);
1850 Op->VectorList.RegNum = RegNum;
1851 Op->VectorList.Count = Count;
1852 Op->StartLoc = S;
1853 Op->EndLoc = E;
1854 return Op;
1855 }
1856
Jim Grosbach98b05a52011-11-30 01:09:44 +00001857 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1858 SMLoc S, SMLoc E) {
1859 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1860 Op->VectorList.RegNum = RegNum;
1861 Op->VectorList.Count = Count;
1862 Op->StartLoc = S;
1863 Op->EndLoc = E;
1864 return Op;
1865 }
1866
Jim Grosbach7636bf62011-12-02 00:35:16 +00001867 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1868 unsigned Index, SMLoc S, SMLoc E) {
1869 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1870 Op->VectorList.RegNum = RegNum;
1871 Op->VectorList.Count = Count;
1872 Op->VectorList.LaneIndex = Index;
1873 Op->StartLoc = S;
1874 Op->EndLoc = E;
1875 return Op;
1876 }
1877
Jim Grosbach460a9052011-10-07 23:56:00 +00001878 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1879 MCContext &Ctx) {
1880 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1881 Op->VectorIndex.Val = Idx;
1882 Op->StartLoc = S;
1883 Op->EndLoc = E;
1884 return Op;
1885 }
1886
Chris Lattner3a697562010-10-28 17:20:03 +00001887 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001889 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001890 Op->StartLoc = S;
1891 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001892 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001893 }
1894
Jim Grosbach9d390362011-10-03 23:38:36 +00001895 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001896 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001897 Op->FPImm.Val = Val;
1898 Op->StartLoc = S;
1899 Op->EndLoc = S;
1900 return Op;
1901 }
1902
Jim Grosbach7ce05792011-08-03 23:50:40 +00001903 static ARMOperand *CreateMem(unsigned BaseRegNum,
1904 const MCConstantExpr *OffsetImm,
1905 unsigned OffsetRegNum,
1906 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001907 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001908 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001909 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001910 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001911 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001912 Op->Memory.BaseRegNum = BaseRegNum;
1913 Op->Memory.OffsetImm = OffsetImm;
1914 Op->Memory.OffsetRegNum = OffsetRegNum;
1915 Op->Memory.ShiftType = ShiftType;
1916 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001917 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001918 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001919 Op->StartLoc = S;
1920 Op->EndLoc = E;
1921 return Op;
1922 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001923
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001924 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1925 ARM_AM::ShiftOpc ShiftTy,
1926 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001927 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001928 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001929 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001930 Op->PostIdxReg.isAdd = isAdd;
1931 Op->PostIdxReg.ShiftTy = ShiftTy;
1932 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001933 Op->StartLoc = S;
1934 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001935 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001936 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001937
1938 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001939 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001940 Op->MBOpt.Val = Opt;
1941 Op->StartLoc = S;
1942 Op->EndLoc = S;
1943 return Op;
1944 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001945
1946 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001947 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001948 Op->IFlags.Val = IFlags;
1949 Op->StartLoc = S;
1950 Op->EndLoc = S;
1951 return Op;
1952 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001953
1954 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001955 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001956 Op->MMask.Val = MMask;
1957 Op->StartLoc = S;
1958 Op->EndLoc = S;
1959 return Op;
1960 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001961};
1962
1963} // end anonymous namespace.
1964
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001965void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001966 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001967 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001968 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1969 << ") >";
1970 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001971 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001972 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001973 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001974 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001975 OS << "<ccout " << getReg() << ">";
1976 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001977 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001978 static const char *MaskStr[] = {
1979 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1980 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1981 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001982 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1983 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1984 break;
1985 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001986 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001987 OS << "<coprocessor number: " << getCoproc() << ">";
1988 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001989 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001990 OS << "<coprocessor register: " << getCoproc() << ">";
1991 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001992 case k_CoprocOption:
1993 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1994 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001995 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001996 OS << "<mask: " << getMSRMask() << ">";
1997 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001998 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001999 getImm()->print(OS);
2000 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002001 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002002 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2003 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002004 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002005 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002006 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002007 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002008 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002009 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002010 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2011 << PostIdxReg.RegNum;
2012 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2013 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2014 << PostIdxReg.ShiftImm;
2015 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002016 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002017 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002018 OS << "<ARM_PROC::";
2019 unsigned IFlags = getProcIFlags();
2020 for (int i=2; i >= 0; --i)
2021 if (IFlags & (1 << i))
2022 OS << ARM_PROC::IFlagsToString(1 << i);
2023 OS << ">";
2024 break;
2025 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002026 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002027 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002028 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002029 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002030 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2031 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002032 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002033 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002034 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002035 << RegShiftedReg.SrcReg << " "
2036 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2037 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002038 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002039 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002040 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002041 << RegShiftedImm.SrcReg << " "
2042 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2043 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002044 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002046 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2047 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002048 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002049 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2050 << ", width: " << Bitfield.Width << ">";
2051 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002052 case k_RegisterList:
2053 case k_DPRRegisterList:
2054 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002055 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002056
Bill Wendling5fa22a12010-11-09 23:28:44 +00002057 const SmallVectorImpl<unsigned> &RegList = getRegList();
2058 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002059 I = RegList.begin(), E = RegList.end(); I != E; ) {
2060 OS << *I;
2061 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002062 }
2063
2064 OS << ">";
2065 break;
2066 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002067 case k_VectorList:
2068 OS << "<vector_list " << VectorList.Count << " * "
2069 << VectorList.RegNum << ">";
2070 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002071 case k_VectorListAllLanes:
2072 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2073 << VectorList.RegNum << ">";
2074 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002075 case k_VectorListIndexed:
2076 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2077 << VectorList.Count << " * " << VectorList.RegNum << ">";
2078 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002079 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002080 OS << "'" << getToken() << "'";
2081 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002082 case k_VectorIndex:
2083 OS << "<vectorindex " << getVectorIndex() << ">";
2084 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002085 }
2086}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002087
2088/// @name Auto-generated Match Functions
2089/// {
2090
2091static unsigned MatchRegisterName(StringRef Name);
2092
2093/// }
2094
Bob Wilson69df7232011-02-03 21:46:10 +00002095bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2096 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002097 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002098
2099 return (RegNo == (unsigned)-1);
2100}
2101
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002102/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002103/// and if it is a register name the token is eaten and the register number is
2104/// returned. Otherwise return -1.
2105///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002106int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002107 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002108 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002109
Chris Lattnere5658fa2010-10-30 04:09:10 +00002110 // FIXME: Validate register for the current architecture; we have to do
2111 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002112 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002113 unsigned RegNum = MatchRegisterName(lowerCase);
2114 if (!RegNum) {
2115 RegNum = StringSwitch<unsigned>(lowerCase)
2116 .Case("r13", ARM::SP)
2117 .Case("r14", ARM::LR)
2118 .Case("r15", ARM::PC)
2119 .Case("ip", ARM::R12)
2120 .Default(0);
2121 }
2122 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002123
Chris Lattnere5658fa2010-10-30 04:09:10 +00002124 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002125
Chris Lattnere5658fa2010-10-30 04:09:10 +00002126 return RegNum;
2127}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002128
Jim Grosbach19906722011-07-13 18:49:30 +00002129// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2130// If a recoverable error occurs, return 1. If an irrecoverable error
2131// occurs, return -1. An irrecoverable error is one where tokens have been
2132// consumed in the process of trying to parse the shifter (i.e., when it is
2133// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002134int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002135 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2136 SMLoc S = Parser.getTok().getLoc();
2137 const AsmToken &Tok = Parser.getTok();
2138 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2139
Benjamin Kramer59085362011-11-06 20:37:06 +00002140 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002141 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2142 .Case("lsl", ARM_AM::lsl)
2143 .Case("lsr", ARM_AM::lsr)
2144 .Case("asr", ARM_AM::asr)
2145 .Case("ror", ARM_AM::ror)
2146 .Case("rrx", ARM_AM::rrx)
2147 .Default(ARM_AM::no_shift);
2148
2149 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002150 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002151
Jim Grosbache8606dc2011-07-13 17:50:29 +00002152 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002153
Jim Grosbache8606dc2011-07-13 17:50:29 +00002154 // The source register for the shift has already been added to the
2155 // operand list, so we need to pop it off and combine it into the shifted
2156 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002157 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002158 if (!PrevOp->isReg())
2159 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2160 int SrcReg = PrevOp->getReg();
2161 int64_t Imm = 0;
2162 int ShiftReg = 0;
2163 if (ShiftTy == ARM_AM::rrx) {
2164 // RRX Doesn't have an explicit shift amount. The encoder expects
2165 // the shift register to be the same as the source register. Seems odd,
2166 // but OK.
2167 ShiftReg = SrcReg;
2168 } else {
2169 // Figure out if this is shifted by a constant or a register (for non-RRX).
2170 if (Parser.getTok().is(AsmToken::Hash)) {
2171 Parser.Lex(); // Eat hash.
2172 SMLoc ImmLoc = Parser.getTok().getLoc();
2173 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002174 if (getParser().ParseExpression(ShiftExpr)) {
2175 Error(ImmLoc, "invalid immediate shift value");
2176 return -1;
2177 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002178 // The expression must be evaluatable as an immediate.
2179 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002180 if (!CE) {
2181 Error(ImmLoc, "invalid immediate shift value");
2182 return -1;
2183 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002184 // Range check the immediate.
2185 // lsl, ror: 0 <= imm <= 31
2186 // lsr, asr: 0 <= imm <= 32
2187 Imm = CE->getValue();
2188 if (Imm < 0 ||
2189 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2190 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002191 Error(ImmLoc, "immediate shift value out of range");
2192 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002193 }
2194 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002195 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002196 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002197 if (ShiftReg == -1) {
2198 Error (L, "expected immediate or register in shift operand");
2199 return -1;
2200 }
2201 } else {
2202 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002203 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002204 return -1;
2205 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002206 }
2207
Owen Anderson92a20222011-07-21 18:54:16 +00002208 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2209 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002210 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002211 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002212 else
2213 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2214 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002215
Jim Grosbach19906722011-07-13 18:49:30 +00002216 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002217}
2218
2219
Bill Wendling50d0f582010-11-18 23:43:05 +00002220/// Try to parse a register name. The token must be an Identifier when called.
2221/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2222/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002223///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002224/// TODO this is likely to change to allow different register types and or to
2225/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002226bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002227tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002228 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002229 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002230 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002231 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002232
Bill Wendling50d0f582010-11-18 23:43:05 +00002233 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002234
Chris Lattnere5658fa2010-10-30 04:09:10 +00002235 const AsmToken &ExclaimTok = Parser.getTok();
2236 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002237 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2238 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002239 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002240 return false;
2241 }
2242
2243 // Also check for an index operand. This is only legal for vector registers,
2244 // but that'll get caught OK in operand matching, so we don't need to
2245 // explicitly filter everything else out here.
2246 if (Parser.getTok().is(AsmToken::LBrac)) {
2247 SMLoc SIdx = Parser.getTok().getLoc();
2248 Parser.Lex(); // Eat left bracket token.
2249
2250 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002251 if (getParser().ParseExpression(ImmVal))
2252 return MatchOperand_ParseFail;
2253 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2254 if (!MCE) {
2255 TokError("immediate value expected for vector index");
2256 return MatchOperand_ParseFail;
2257 }
2258
2259 SMLoc E = Parser.getTok().getLoc();
2260 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2261 Error(E, "']' expected");
2262 return MatchOperand_ParseFail;
2263 }
2264
2265 Parser.Lex(); // Eat right bracket token.
2266
2267 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2268 SIdx, E,
2269 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002270 }
2271
Bill Wendling50d0f582010-11-18 23:43:05 +00002272 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002273}
2274
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002275/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2276/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2277/// "c5", ...
2278static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002279 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2280 // but efficient.
2281 switch (Name.size()) {
2282 default: break;
2283 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002284 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002285 return -1;
2286 switch (Name[1]) {
2287 default: return -1;
2288 case '0': return 0;
2289 case '1': return 1;
2290 case '2': return 2;
2291 case '3': return 3;
2292 case '4': return 4;
2293 case '5': return 5;
2294 case '6': return 6;
2295 case '7': return 7;
2296 case '8': return 8;
2297 case '9': return 9;
2298 }
2299 break;
2300 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002301 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002302 return -1;
2303 switch (Name[2]) {
2304 default: return -1;
2305 case '0': return 10;
2306 case '1': return 11;
2307 case '2': return 12;
2308 case '3': return 13;
2309 case '4': return 14;
2310 case '5': return 15;
2311 }
2312 break;
2313 }
2314
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002315 return -1;
2316}
2317
Jim Grosbach89df9962011-08-26 21:43:41 +00002318/// parseITCondCode - Try to parse a condition code for an IT instruction.
2319ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2320parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2321 SMLoc S = Parser.getTok().getLoc();
2322 const AsmToken &Tok = Parser.getTok();
2323 if (!Tok.is(AsmToken::Identifier))
2324 return MatchOperand_NoMatch;
2325 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2326 .Case("eq", ARMCC::EQ)
2327 .Case("ne", ARMCC::NE)
2328 .Case("hs", ARMCC::HS)
2329 .Case("cs", ARMCC::HS)
2330 .Case("lo", ARMCC::LO)
2331 .Case("cc", ARMCC::LO)
2332 .Case("mi", ARMCC::MI)
2333 .Case("pl", ARMCC::PL)
2334 .Case("vs", ARMCC::VS)
2335 .Case("vc", ARMCC::VC)
2336 .Case("hi", ARMCC::HI)
2337 .Case("ls", ARMCC::LS)
2338 .Case("ge", ARMCC::GE)
2339 .Case("lt", ARMCC::LT)
2340 .Case("gt", ARMCC::GT)
2341 .Case("le", ARMCC::LE)
2342 .Case("al", ARMCC::AL)
2343 .Default(~0U);
2344 if (CC == ~0U)
2345 return MatchOperand_NoMatch;
2346 Parser.Lex(); // Eat the token.
2347
2348 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2349
2350 return MatchOperand_Success;
2351}
2352
Jim Grosbach43904292011-07-25 20:14:50 +00002353/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002354/// token must be an Identifier when called, and if it is a coprocessor
2355/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002356ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002357parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002358 SMLoc S = Parser.getTok().getLoc();
2359 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002360 if (Tok.isNot(AsmToken::Identifier))
2361 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002362
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002363 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002364 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002365 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002366
2367 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002368 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002369 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002370}
2371
Jim Grosbach43904292011-07-25 20:14:50 +00002372/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002373/// token must be an Identifier when called, and if it is a coprocessor
2374/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002375ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002376parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002377 SMLoc S = Parser.getTok().getLoc();
2378 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002379 if (Tok.isNot(AsmToken::Identifier))
2380 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002381
2382 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2383 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002384 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002385
2386 Parser.Lex(); // Eat identifier token.
2387 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002388 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002389}
2390
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002391/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2392/// coproc_option : '{' imm0_255 '}'
2393ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2394parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2395 SMLoc S = Parser.getTok().getLoc();
2396
2397 // If this isn't a '{', this isn't a coprocessor immediate operand.
2398 if (Parser.getTok().isNot(AsmToken::LCurly))
2399 return MatchOperand_NoMatch;
2400 Parser.Lex(); // Eat the '{'
2401
2402 const MCExpr *Expr;
2403 SMLoc Loc = Parser.getTok().getLoc();
2404 if (getParser().ParseExpression(Expr)) {
2405 Error(Loc, "illegal expression");
2406 return MatchOperand_ParseFail;
2407 }
2408 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2409 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2410 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2411 return MatchOperand_ParseFail;
2412 }
2413 int Val = CE->getValue();
2414
2415 // Check for and consume the closing '}'
2416 if (Parser.getTok().isNot(AsmToken::RCurly))
2417 return MatchOperand_ParseFail;
2418 SMLoc E = Parser.getTok().getLoc();
2419 Parser.Lex(); // Eat the '}'
2420
2421 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2422 return MatchOperand_Success;
2423}
2424
Jim Grosbachd0588e22011-09-14 18:08:35 +00002425// For register list parsing, we need to map from raw GPR register numbering
2426// to the enumeration values. The enumeration values aren't sorted by
2427// register number due to our using "sp", "lr" and "pc" as canonical names.
2428static unsigned getNextRegister(unsigned Reg) {
2429 // If this is a GPR, we need to do it manually, otherwise we can rely
2430 // on the sort ordering of the enumeration since the other reg-classes
2431 // are sane.
2432 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2433 return Reg + 1;
2434 switch(Reg) {
2435 default: assert(0 && "Invalid GPR number!");
2436 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2437 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2438 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2439 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2440 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2441 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2442 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2443 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2444 }
2445}
2446
Jim Grosbachce485e72011-11-11 21:27:40 +00002447// Return the low-subreg of a given Q register.
2448static unsigned getDRegFromQReg(unsigned QReg) {
2449 switch (QReg) {
2450 default: llvm_unreachable("expected a Q register!");
2451 case ARM::Q0: return ARM::D0;
2452 case ARM::Q1: return ARM::D2;
2453 case ARM::Q2: return ARM::D4;
2454 case ARM::Q3: return ARM::D6;
2455 case ARM::Q4: return ARM::D8;
2456 case ARM::Q5: return ARM::D10;
2457 case ARM::Q6: return ARM::D12;
2458 case ARM::Q7: return ARM::D14;
2459 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002460 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002461 case ARM::Q10: return ARM::D20;
2462 case ARM::Q11: return ARM::D22;
2463 case ARM::Q12: return ARM::D24;
2464 case ARM::Q13: return ARM::D26;
2465 case ARM::Q14: return ARM::D28;
2466 case ARM::Q15: return ARM::D30;
2467 }
2468}
2469
Jim Grosbachd0588e22011-09-14 18:08:35 +00002470/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002471bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002472parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002473 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002474 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002475 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002476 Parser.Lex(); // Eat '{' token.
2477 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002478
Jim Grosbachd0588e22011-09-14 18:08:35 +00002479 // Check the first register in the list to see what register class
2480 // this is a list of.
2481 int Reg = tryParseRegister();
2482 if (Reg == -1)
2483 return Error(RegLoc, "register expected");
2484
Jim Grosbachce485e72011-11-11 21:27:40 +00002485 // The reglist instructions have at most 16 registers, so reserve
2486 // space for that many.
2487 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2488
2489 // Allow Q regs and just interpret them as the two D sub-registers.
2490 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2491 Reg = getDRegFromQReg(Reg);
2492 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2493 ++Reg;
2494 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002495 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002496 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2497 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2498 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2499 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2500 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2501 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2502 else
2503 return Error(RegLoc, "invalid register in register list");
2504
Jim Grosbachce485e72011-11-11 21:27:40 +00002505 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002506 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002507
Jim Grosbachd0588e22011-09-14 18:08:35 +00002508 // This starts immediately after the first register token in the list,
2509 // so we can see either a comma or a minus (range separator) as a legal
2510 // next token.
2511 while (Parser.getTok().is(AsmToken::Comma) ||
2512 Parser.getTok().is(AsmToken::Minus)) {
2513 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002514 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002515 SMLoc EndLoc = Parser.getTok().getLoc();
2516 int EndReg = tryParseRegister();
2517 if (EndReg == -1)
2518 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002519 // Allow Q regs and just interpret them as the two D sub-registers.
2520 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2521 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002522 // If the register is the same as the start reg, there's nothing
2523 // more to do.
2524 if (Reg == EndReg)
2525 continue;
2526 // The register must be in the same register class as the first.
2527 if (!RC->contains(EndReg))
2528 return Error(EndLoc, "invalid register in register list");
2529 // Ranges must go from low to high.
2530 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2531 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002532
Jim Grosbachd0588e22011-09-14 18:08:35 +00002533 // Add all the registers in the range to the register list.
2534 while (Reg != EndReg) {
2535 Reg = getNextRegister(Reg);
2536 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2537 }
2538 continue;
2539 }
2540 Parser.Lex(); // Eat the comma.
2541 RegLoc = Parser.getTok().getLoc();
2542 int OldReg = Reg;
2543 Reg = tryParseRegister();
2544 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002545 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002546 // Allow Q regs and just interpret them as the two D sub-registers.
2547 bool isQReg = false;
2548 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2549 Reg = getDRegFromQReg(Reg);
2550 isQReg = true;
2551 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002552 // The register must be in the same register class as the first.
2553 if (!RC->contains(Reg))
2554 return Error(RegLoc, "invalid register in register list");
2555 // List must be monotonically increasing.
2556 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2557 return Error(RegLoc, "register list not in ascending order");
2558 // VFP register lists must also be contiguous.
2559 // It's OK to use the enumeration values directly here rather, as the
2560 // VFP register classes have the enum sorted properly.
2561 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2562 Reg != OldReg + 1)
2563 return Error(RegLoc, "non-contiguous register range");
2564 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002565 if (isQReg)
2566 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002567 }
2568
Jim Grosbachd0588e22011-09-14 18:08:35 +00002569 SMLoc E = Parser.getTok().getLoc();
2570 if (Parser.getTok().isNot(AsmToken::RCurly))
2571 return Error(E, "'}' expected");
2572 Parser.Lex(); // Eat '}' token.
2573
Bill Wendling50d0f582010-11-18 23:43:05 +00002574 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2575 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002576}
2577
Jim Grosbach98b05a52011-11-30 01:09:44 +00002578// Helper function to parse the lane index for vector lists.
2579ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002580parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2581 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002582 if (Parser.getTok().is(AsmToken::LBrac)) {
2583 Parser.Lex(); // Eat the '['.
2584 if (Parser.getTok().is(AsmToken::RBrac)) {
2585 // "Dn[]" is the 'all lanes' syntax.
2586 LaneKind = AllLanes;
2587 Parser.Lex(); // Eat the ']'.
2588 return MatchOperand_Success;
2589 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002590 if (Parser.getTok().is(AsmToken::Integer)) {
2591 int64_t Val = Parser.getTok().getIntVal();
2592 // Make this range check context sensitive for .8, .16, .32.
2593 if (Val < 0 && Val > 7)
2594 Error(Parser.getTok().getLoc(), "lane index out of range");
2595 Index = Val;
2596 LaneKind = IndexedLane;
2597 Parser.Lex(); // Eat the token;
2598 if (Parser.getTok().isNot(AsmToken::RBrac))
2599 Error(Parser.getTok().getLoc(), "']' expected");
2600 Parser.Lex(); // Eat the ']'.
2601 return MatchOperand_Success;
2602 }
2603 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002604 return MatchOperand_ParseFail;
2605 }
2606 LaneKind = NoLanes;
2607 return MatchOperand_Success;
2608}
2609
Jim Grosbach862019c2011-10-18 23:02:30 +00002610// parse a vector register list
2611ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2612parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002613 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002614 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002615 SMLoc S = Parser.getTok().getLoc();
2616 // As an extension (to match gas), support a plain D register or Q register
2617 // (without encosing curly braces) as a single or double entry list,
2618 // respectively.
2619 if (Parser.getTok().is(AsmToken::Identifier)) {
2620 int Reg = tryParseRegister();
2621 if (Reg == -1)
2622 return MatchOperand_NoMatch;
2623 SMLoc E = Parser.getTok().getLoc();
2624 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002625 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002626 if (Res != MatchOperand_Success)
2627 return Res;
2628 switch (LaneKind) {
2629 default:
2630 assert(0 && "unexpected lane kind!");
2631 case NoLanes:
2632 E = Parser.getTok().getLoc();
2633 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2634 break;
2635 case AllLanes:
2636 E = Parser.getTok().getLoc();
2637 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2638 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002639 case IndexedLane:
2640 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2641 LaneIndex, S,E));
2642 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002643 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002644 return MatchOperand_Success;
2645 }
2646 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2647 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002648 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002649 if (Res != MatchOperand_Success)
2650 return Res;
2651 switch (LaneKind) {
2652 default:
2653 assert(0 && "unexpected lane kind!");
2654 case NoLanes:
2655 E = Parser.getTok().getLoc();
2656 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2657 break;
2658 case AllLanes:
2659 E = Parser.getTok().getLoc();
2660 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2661 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002662 case IndexedLane:
2663 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2664 LaneIndex, S,E));
2665 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002666 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002667 return MatchOperand_Success;
2668 }
2669 Error(S, "vector register expected");
2670 return MatchOperand_ParseFail;
2671 }
2672
2673 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002674 return MatchOperand_NoMatch;
2675
Jim Grosbach862019c2011-10-18 23:02:30 +00002676 Parser.Lex(); // Eat '{' token.
2677 SMLoc RegLoc = Parser.getTok().getLoc();
2678
2679 int Reg = tryParseRegister();
2680 if (Reg == -1) {
2681 Error(RegLoc, "register expected");
2682 return MatchOperand_ParseFail;
2683 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002684 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002685 unsigned FirstReg = Reg;
2686 // The list is of D registers, but we also allow Q regs and just interpret
2687 // them as the two D sub-registers.
2688 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2689 FirstReg = Reg = getDRegFromQReg(Reg);
2690 ++Reg;
2691 ++Count;
2692 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002693 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002694 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002695
Jim Grosbache43862b2011-11-15 23:19:15 +00002696 while (Parser.getTok().is(AsmToken::Comma) ||
2697 Parser.getTok().is(AsmToken::Minus)) {
2698 if (Parser.getTok().is(AsmToken::Minus)) {
2699 Parser.Lex(); // Eat the minus.
2700 SMLoc EndLoc = Parser.getTok().getLoc();
2701 int EndReg = tryParseRegister();
2702 if (EndReg == -1) {
2703 Error(EndLoc, "register expected");
2704 return MatchOperand_ParseFail;
2705 }
2706 // Allow Q regs and just interpret them as the two D sub-registers.
2707 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2708 EndReg = getDRegFromQReg(EndReg) + 1;
2709 // If the register is the same as the start reg, there's nothing
2710 // more to do.
2711 if (Reg == EndReg)
2712 continue;
2713 // The register must be in the same register class as the first.
2714 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2715 Error(EndLoc, "invalid register in register list");
2716 return MatchOperand_ParseFail;
2717 }
2718 // Ranges must go from low to high.
2719 if (Reg > EndReg) {
2720 Error(EndLoc, "bad range in register list");
2721 return MatchOperand_ParseFail;
2722 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002723 // Parse the lane specifier if present.
2724 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002725 unsigned NextLaneIndex;
2726 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002727 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002728 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002729 Error(EndLoc, "mismatched lane index in register list");
2730 return MatchOperand_ParseFail;
2731 }
2732 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002733
2734 // Add all the registers in the range to the register list.
2735 Count += EndReg - Reg;
2736 Reg = EndReg;
2737 continue;
2738 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002739 Parser.Lex(); // Eat the comma.
2740 RegLoc = Parser.getTok().getLoc();
2741 int OldReg = Reg;
2742 Reg = tryParseRegister();
2743 if (Reg == -1) {
2744 Error(RegLoc, "register expected");
2745 return MatchOperand_ParseFail;
2746 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002747 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002748 // It's OK to use the enumeration values directly here rather, as the
2749 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002750 //
2751 // The list is of D registers, but we also allow Q regs and just interpret
2752 // them as the two D sub-registers.
2753 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2754 Reg = getDRegFromQReg(Reg);
2755 if (Reg != OldReg + 1) {
2756 Error(RegLoc, "non-contiguous register range");
2757 return MatchOperand_ParseFail;
2758 }
2759 ++Reg;
2760 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002761 // Parse the lane specifier if present.
2762 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002763 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002764 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002765 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002766 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002767 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002768 Error(EndLoc, "mismatched lane index in register list");
2769 return MatchOperand_ParseFail;
2770 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002771 continue;
2772 }
2773 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002774 if (Reg != OldReg + 1) {
2775 Error(RegLoc, "non-contiguous register range");
2776 return MatchOperand_ParseFail;
2777 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002778 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002779 // Parse the lane specifier if present.
2780 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002781 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002782 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002783 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002784 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002785 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002786 Error(EndLoc, "mismatched lane index in register list");
2787 return MatchOperand_ParseFail;
2788 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002789 }
2790
2791 SMLoc E = Parser.getTok().getLoc();
2792 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2793 Error(E, "'}' expected");
2794 return MatchOperand_ParseFail;
2795 }
2796 Parser.Lex(); // Eat '}' token.
2797
Jim Grosbach98b05a52011-11-30 01:09:44 +00002798 switch (LaneKind) {
2799 default:
2800 assert(0 && "unexpected lane kind in register list.");
2801 case NoLanes:
2802 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2803 break;
2804 case AllLanes:
2805 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2806 S, E));
2807 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002808 case IndexedLane:
2809 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2810 LaneIndex, S, E));
2811 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002812 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002813 return MatchOperand_Success;
2814}
2815
Jim Grosbach43904292011-07-25 20:14:50 +00002816/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002817ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002818parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002819 SMLoc S = Parser.getTok().getLoc();
2820 const AsmToken &Tok = Parser.getTok();
2821 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2822 StringRef OptStr = Tok.getString();
2823
2824 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2825 .Case("sy", ARM_MB::SY)
2826 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002827 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002828 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002829 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002830 .Case("ishst", ARM_MB::ISHST)
2831 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002832 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002833 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002834 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002835 .Case("osh", ARM_MB::OSH)
2836 .Case("oshst", ARM_MB::OSHST)
2837 .Default(~0U);
2838
2839 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002840 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002841
2842 Parser.Lex(); // Eat identifier token.
2843 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002844 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002845}
2846
Jim Grosbach43904292011-07-25 20:14:50 +00002847/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002848ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002849parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002850 SMLoc S = Parser.getTok().getLoc();
2851 const AsmToken &Tok = Parser.getTok();
2852 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2853 StringRef IFlagsStr = Tok.getString();
2854
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002855 // An iflags string of "none" is interpreted to mean that none of the AIF
2856 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002857 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002858 if (IFlagsStr != "none") {
2859 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2860 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2861 .Case("a", ARM_PROC::A)
2862 .Case("i", ARM_PROC::I)
2863 .Case("f", ARM_PROC::F)
2864 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002865
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002866 // If some specific iflag is already set, it means that some letter is
2867 // present more than once, this is not acceptable.
2868 if (Flag == ~0U || (IFlags & Flag))
2869 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002870
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002871 IFlags |= Flag;
2872 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002873 }
2874
2875 Parser.Lex(); // Eat identifier token.
2876 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2877 return MatchOperand_Success;
2878}
2879
Jim Grosbach43904292011-07-25 20:14:50 +00002880/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002881ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002882parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002883 SMLoc S = Parser.getTok().getLoc();
2884 const AsmToken &Tok = Parser.getTok();
2885 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2886 StringRef Mask = Tok.getString();
2887
James Molloyacad68d2011-09-28 14:21:38 +00002888 if (isMClass()) {
2889 // See ARMv6-M 10.1.1
2890 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2891 .Case("apsr", 0)
2892 .Case("iapsr", 1)
2893 .Case("eapsr", 2)
2894 .Case("xpsr", 3)
2895 .Case("ipsr", 5)
2896 .Case("epsr", 6)
2897 .Case("iepsr", 7)
2898 .Case("msp", 8)
2899 .Case("psp", 9)
2900 .Case("primask", 16)
2901 .Case("basepri", 17)
2902 .Case("basepri_max", 18)
2903 .Case("faultmask", 19)
2904 .Case("control", 20)
2905 .Default(~0U);
2906
2907 if (FlagsVal == ~0U)
2908 return MatchOperand_NoMatch;
2909
2910 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2911 // basepri, basepri_max and faultmask only valid for V7m.
2912 return MatchOperand_NoMatch;
2913
2914 Parser.Lex(); // Eat identifier token.
2915 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2916 return MatchOperand_Success;
2917 }
2918
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002919 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2920 size_t Start = 0, Next = Mask.find('_');
2921 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002922 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002923 if (Next != StringRef::npos)
2924 Flags = Mask.slice(Next+1, Mask.size());
2925
2926 // FlagsVal contains the complete mask:
2927 // 3-0: Mask
2928 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2929 unsigned FlagsVal = 0;
2930
2931 if (SpecReg == "apsr") {
2932 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002933 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002934 .Case("g", 0x4) // same as CPSR_s
2935 .Case("nzcvqg", 0xc) // same as CPSR_fs
2936 .Default(~0U);
2937
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002938 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002939 if (!Flags.empty())
2940 return MatchOperand_NoMatch;
2941 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002942 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002943 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002944 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002945 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2946 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002947 for (int i = 0, e = Flags.size(); i != e; ++i) {
2948 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2949 .Case("c", 1)
2950 .Case("x", 2)
2951 .Case("s", 4)
2952 .Case("f", 8)
2953 .Default(~0U);
2954
2955 // If some specific flag is already set, it means that some letter is
2956 // present more than once, this is not acceptable.
2957 if (FlagsVal == ~0U || (FlagsVal & Flag))
2958 return MatchOperand_NoMatch;
2959 FlagsVal |= Flag;
2960 }
2961 } else // No match for special register.
2962 return MatchOperand_NoMatch;
2963
Owen Anderson7784f1d2011-10-21 18:43:28 +00002964 // Special register without flags is NOT equivalent to "fc" flags.
2965 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2966 // two lines would enable gas compatibility at the expense of breaking
2967 // round-tripping.
2968 //
2969 // if (!FlagsVal)
2970 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002971
2972 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2973 if (SpecReg == "spsr")
2974 FlagsVal |= 16;
2975
2976 Parser.Lex(); // Eat identifier token.
2977 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2978 return MatchOperand_Success;
2979}
2980
Jim Grosbachf6c05252011-07-21 17:23:04 +00002981ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2982parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2983 int Low, int High) {
2984 const AsmToken &Tok = Parser.getTok();
2985 if (Tok.isNot(AsmToken::Identifier)) {
2986 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2987 return MatchOperand_ParseFail;
2988 }
2989 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002990 std::string LowerOp = Op.lower();
2991 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002992 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2993 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2994 return MatchOperand_ParseFail;
2995 }
2996 Parser.Lex(); // Eat shift type token.
2997
2998 // There must be a '#' and a shift amount.
2999 if (Parser.getTok().isNot(AsmToken::Hash)) {
3000 Error(Parser.getTok().getLoc(), "'#' expected");
3001 return MatchOperand_ParseFail;
3002 }
3003 Parser.Lex(); // Eat hash token.
3004
3005 const MCExpr *ShiftAmount;
3006 SMLoc Loc = Parser.getTok().getLoc();
3007 if (getParser().ParseExpression(ShiftAmount)) {
3008 Error(Loc, "illegal expression");
3009 return MatchOperand_ParseFail;
3010 }
3011 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3012 if (!CE) {
3013 Error(Loc, "constant expression expected");
3014 return MatchOperand_ParseFail;
3015 }
3016 int Val = CE->getValue();
3017 if (Val < Low || Val > High) {
3018 Error(Loc, "immediate value out of range");
3019 return MatchOperand_ParseFail;
3020 }
3021
3022 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3023
3024 return MatchOperand_Success;
3025}
3026
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003027ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3028parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3029 const AsmToken &Tok = Parser.getTok();
3030 SMLoc S = Tok.getLoc();
3031 if (Tok.isNot(AsmToken::Identifier)) {
3032 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3033 return MatchOperand_ParseFail;
3034 }
3035 int Val = StringSwitch<int>(Tok.getString())
3036 .Case("be", 1)
3037 .Case("le", 0)
3038 .Default(-1);
3039 Parser.Lex(); // Eat the token.
3040
3041 if (Val == -1) {
3042 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3043 return MatchOperand_ParseFail;
3044 }
3045 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3046 getContext()),
3047 S, Parser.getTok().getLoc()));
3048 return MatchOperand_Success;
3049}
3050
Jim Grosbach580f4a92011-07-25 22:20:28 +00003051/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3052/// instructions. Legal values are:
3053/// lsl #n 'n' in [0,31]
3054/// asr #n 'n' in [1,32]
3055/// n == 32 encoded as n == 0.
3056ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3057parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3058 const AsmToken &Tok = Parser.getTok();
3059 SMLoc S = Tok.getLoc();
3060 if (Tok.isNot(AsmToken::Identifier)) {
3061 Error(S, "shift operator 'asr' or 'lsl' expected");
3062 return MatchOperand_ParseFail;
3063 }
3064 StringRef ShiftName = Tok.getString();
3065 bool isASR;
3066 if (ShiftName == "lsl" || ShiftName == "LSL")
3067 isASR = false;
3068 else if (ShiftName == "asr" || ShiftName == "ASR")
3069 isASR = true;
3070 else {
3071 Error(S, "shift operator 'asr' or 'lsl' expected");
3072 return MatchOperand_ParseFail;
3073 }
3074 Parser.Lex(); // Eat the operator.
3075
3076 // A '#' and a shift amount.
3077 if (Parser.getTok().isNot(AsmToken::Hash)) {
3078 Error(Parser.getTok().getLoc(), "'#' expected");
3079 return MatchOperand_ParseFail;
3080 }
3081 Parser.Lex(); // Eat hash token.
3082
3083 const MCExpr *ShiftAmount;
3084 SMLoc E = Parser.getTok().getLoc();
3085 if (getParser().ParseExpression(ShiftAmount)) {
3086 Error(E, "malformed shift expression");
3087 return MatchOperand_ParseFail;
3088 }
3089 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3090 if (!CE) {
3091 Error(E, "shift amount must be an immediate");
3092 return MatchOperand_ParseFail;
3093 }
3094
3095 int64_t Val = CE->getValue();
3096 if (isASR) {
3097 // Shift amount must be in [1,32]
3098 if (Val < 1 || Val > 32) {
3099 Error(E, "'asr' shift amount must be in range [1,32]");
3100 return MatchOperand_ParseFail;
3101 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003102 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3103 if (isThumb() && Val == 32) {
3104 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3105 return MatchOperand_ParseFail;
3106 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003107 if (Val == 32) Val = 0;
3108 } else {
3109 // Shift amount must be in [1,32]
3110 if (Val < 0 || Val > 31) {
3111 Error(E, "'lsr' shift amount must be in range [0,31]");
3112 return MatchOperand_ParseFail;
3113 }
3114 }
3115
3116 E = Parser.getTok().getLoc();
3117 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3118
3119 return MatchOperand_Success;
3120}
3121
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003122/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3123/// of instructions. Legal values are:
3124/// ror #n 'n' in {0, 8, 16, 24}
3125ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3126parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3127 const AsmToken &Tok = Parser.getTok();
3128 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003129 if (Tok.isNot(AsmToken::Identifier))
3130 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003131 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003132 if (ShiftName != "ror" && ShiftName != "ROR")
3133 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003134 Parser.Lex(); // Eat the operator.
3135
3136 // A '#' and a rotate amount.
3137 if (Parser.getTok().isNot(AsmToken::Hash)) {
3138 Error(Parser.getTok().getLoc(), "'#' expected");
3139 return MatchOperand_ParseFail;
3140 }
3141 Parser.Lex(); // Eat hash token.
3142
3143 const MCExpr *ShiftAmount;
3144 SMLoc E = Parser.getTok().getLoc();
3145 if (getParser().ParseExpression(ShiftAmount)) {
3146 Error(E, "malformed rotate expression");
3147 return MatchOperand_ParseFail;
3148 }
3149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3150 if (!CE) {
3151 Error(E, "rotate amount must be an immediate");
3152 return MatchOperand_ParseFail;
3153 }
3154
3155 int64_t Val = CE->getValue();
3156 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3157 // normally, zero is represented in asm by omitting the rotate operand
3158 // entirely.
3159 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3160 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3161 return MatchOperand_ParseFail;
3162 }
3163
3164 E = Parser.getTok().getLoc();
3165 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3166
3167 return MatchOperand_Success;
3168}
3169
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003170ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3171parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3172 SMLoc S = Parser.getTok().getLoc();
3173 // The bitfield descriptor is really two operands, the LSB and the width.
3174 if (Parser.getTok().isNot(AsmToken::Hash)) {
3175 Error(Parser.getTok().getLoc(), "'#' expected");
3176 return MatchOperand_ParseFail;
3177 }
3178 Parser.Lex(); // Eat hash token.
3179
3180 const MCExpr *LSBExpr;
3181 SMLoc E = Parser.getTok().getLoc();
3182 if (getParser().ParseExpression(LSBExpr)) {
3183 Error(E, "malformed immediate expression");
3184 return MatchOperand_ParseFail;
3185 }
3186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3187 if (!CE) {
3188 Error(E, "'lsb' operand must be an immediate");
3189 return MatchOperand_ParseFail;
3190 }
3191
3192 int64_t LSB = CE->getValue();
3193 // The LSB must be in the range [0,31]
3194 if (LSB < 0 || LSB > 31) {
3195 Error(E, "'lsb' operand must be in the range [0,31]");
3196 return MatchOperand_ParseFail;
3197 }
3198 E = Parser.getTok().getLoc();
3199
3200 // Expect another immediate operand.
3201 if (Parser.getTok().isNot(AsmToken::Comma)) {
3202 Error(Parser.getTok().getLoc(), "too few operands");
3203 return MatchOperand_ParseFail;
3204 }
3205 Parser.Lex(); // Eat hash token.
3206 if (Parser.getTok().isNot(AsmToken::Hash)) {
3207 Error(Parser.getTok().getLoc(), "'#' expected");
3208 return MatchOperand_ParseFail;
3209 }
3210 Parser.Lex(); // Eat hash token.
3211
3212 const MCExpr *WidthExpr;
3213 if (getParser().ParseExpression(WidthExpr)) {
3214 Error(E, "malformed immediate expression");
3215 return MatchOperand_ParseFail;
3216 }
3217 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3218 if (!CE) {
3219 Error(E, "'width' operand must be an immediate");
3220 return MatchOperand_ParseFail;
3221 }
3222
3223 int64_t Width = CE->getValue();
3224 // The LSB must be in the range [1,32-lsb]
3225 if (Width < 1 || Width > 32 - LSB) {
3226 Error(E, "'width' operand must be in the range [1,32-lsb]");
3227 return MatchOperand_ParseFail;
3228 }
3229 E = Parser.getTok().getLoc();
3230
3231 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3232
3233 return MatchOperand_Success;
3234}
3235
Jim Grosbach7ce05792011-08-03 23:50:40 +00003236ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3237parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3238 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003239 // postidx_reg := '+' register {, shift}
3240 // | '-' register {, shift}
3241 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003242
3243 // This method must return MatchOperand_NoMatch without consuming any tokens
3244 // in the case where there is no match, as other alternatives take other
3245 // parse methods.
3246 AsmToken Tok = Parser.getTok();
3247 SMLoc S = Tok.getLoc();
3248 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003249 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003250 int Reg = -1;
3251 if (Tok.is(AsmToken::Plus)) {
3252 Parser.Lex(); // Eat the '+' token.
3253 haveEaten = true;
3254 } else if (Tok.is(AsmToken::Minus)) {
3255 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003256 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003257 haveEaten = true;
3258 }
3259 if (Parser.getTok().is(AsmToken::Identifier))
3260 Reg = tryParseRegister();
3261 if (Reg == -1) {
3262 if (!haveEaten)
3263 return MatchOperand_NoMatch;
3264 Error(Parser.getTok().getLoc(), "register expected");
3265 return MatchOperand_ParseFail;
3266 }
3267 SMLoc E = Parser.getTok().getLoc();
3268
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003269 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3270 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003271 if (Parser.getTok().is(AsmToken::Comma)) {
3272 Parser.Lex(); // Eat the ','.
3273 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3274 return MatchOperand_ParseFail;
3275 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003276
3277 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3278 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003279
3280 return MatchOperand_Success;
3281}
3282
Jim Grosbach251bf252011-08-10 21:56:18 +00003283ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3284parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3285 // Check for a post-index addressing register operand. Specifically:
3286 // am3offset := '+' register
3287 // | '-' register
3288 // | register
3289 // | # imm
3290 // | # + imm
3291 // | # - imm
3292
3293 // This method must return MatchOperand_NoMatch without consuming any tokens
3294 // in the case where there is no match, as other alternatives take other
3295 // parse methods.
3296 AsmToken Tok = Parser.getTok();
3297 SMLoc S = Tok.getLoc();
3298
3299 // Do immediates first, as we always parse those if we have a '#'.
3300 if (Parser.getTok().is(AsmToken::Hash)) {
3301 Parser.Lex(); // Eat the '#'.
3302 // Explicitly look for a '-', as we need to encode negative zero
3303 // differently.
3304 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3305 const MCExpr *Offset;
3306 if (getParser().ParseExpression(Offset))
3307 return MatchOperand_ParseFail;
3308 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3309 if (!CE) {
3310 Error(S, "constant expression expected");
3311 return MatchOperand_ParseFail;
3312 }
3313 SMLoc E = Tok.getLoc();
3314 // Negative zero is encoded as the flag value INT32_MIN.
3315 int32_t Val = CE->getValue();
3316 if (isNegative && Val == 0)
3317 Val = INT32_MIN;
3318
3319 Operands.push_back(
3320 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3321
3322 return MatchOperand_Success;
3323 }
3324
3325
3326 bool haveEaten = false;
3327 bool isAdd = true;
3328 int Reg = -1;
3329 if (Tok.is(AsmToken::Plus)) {
3330 Parser.Lex(); // Eat the '+' token.
3331 haveEaten = true;
3332 } else if (Tok.is(AsmToken::Minus)) {
3333 Parser.Lex(); // Eat the '-' token.
3334 isAdd = false;
3335 haveEaten = true;
3336 }
3337 if (Parser.getTok().is(AsmToken::Identifier))
3338 Reg = tryParseRegister();
3339 if (Reg == -1) {
3340 if (!haveEaten)
3341 return MatchOperand_NoMatch;
3342 Error(Parser.getTok().getLoc(), "register expected");
3343 return MatchOperand_ParseFail;
3344 }
3345 SMLoc E = Parser.getTok().getLoc();
3346
3347 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3348 0, S, E));
3349
3350 return MatchOperand_Success;
3351}
3352
Jim Grosbacha77295d2011-09-08 22:07:06 +00003353/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3354/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3355/// when they refer multiple MIOperands inside a single one.
3356bool ARMAsmParser::
3357cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3358 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3359 // Rt, Rt2
3360 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3361 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3362 // Create a writeback register dummy placeholder.
3363 Inst.addOperand(MCOperand::CreateReg(0));
3364 // addr
3365 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3366 // pred
3367 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3368 return true;
3369}
3370
3371/// cvtT2StrdPre - Convert parsed operands to MCInst.
3372/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3373/// when they refer multiple MIOperands inside a single one.
3374bool ARMAsmParser::
3375cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3376 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3377 // Create a writeback register dummy placeholder.
3378 Inst.addOperand(MCOperand::CreateReg(0));
3379 // Rt, Rt2
3380 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3381 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3382 // addr
3383 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3384 // pred
3385 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3386 return true;
3387}
3388
Jim Grosbacheeec0252011-09-08 00:39:19 +00003389/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3390/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3391/// when they refer multiple MIOperands inside a single one.
3392bool ARMAsmParser::
3393cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3394 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3395 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3396
3397 // Create a writeback register dummy placeholder.
3398 Inst.addOperand(MCOperand::CreateImm(0));
3399
3400 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3401 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3402 return true;
3403}
3404
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003405/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3406/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3407/// when they refer multiple MIOperands inside a single one.
3408bool ARMAsmParser::
3409cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3410 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3411 // Create a writeback register dummy placeholder.
3412 Inst.addOperand(MCOperand::CreateImm(0));
3413 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3414 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3415 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3416 return true;
3417}
3418
Jim Grosbach1355cf12011-07-26 17:10:22 +00003419/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003420/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3421/// when they refer multiple MIOperands inside a single one.
3422bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003423cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003424 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3425 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3426
3427 // Create a writeback register dummy placeholder.
3428 Inst.addOperand(MCOperand::CreateImm(0));
3429
Jim Grosbach7ce05792011-08-03 23:50:40 +00003430 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003431 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3432 return true;
3433}
3434
Owen Anderson9ab0f252011-08-26 20:43:14 +00003435/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3436/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3437/// when they refer multiple MIOperands inside a single one.
3438bool ARMAsmParser::
3439cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3440 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3441 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3442
3443 // Create a writeback register dummy placeholder.
3444 Inst.addOperand(MCOperand::CreateImm(0));
3445
3446 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3447 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3448 return true;
3449}
3450
3451
Jim Grosbach548340c2011-08-11 19:22:40 +00003452/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3453/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3454/// when they refer multiple MIOperands inside a single one.
3455bool ARMAsmParser::
3456cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3457 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3458 // Create a writeback register dummy placeholder.
3459 Inst.addOperand(MCOperand::CreateImm(0));
3460 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3461 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3462 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3463 return true;
3464}
3465
Jim Grosbach1355cf12011-07-26 17:10:22 +00003466/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003467/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3468/// when they refer multiple MIOperands inside a single one.
3469bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003470cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003471 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3472 // Create a writeback register dummy placeholder.
3473 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003474 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3475 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3476 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003477 return true;
3478}
3479
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003480/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3481/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3482/// when they refer multiple MIOperands inside a single one.
3483bool ARMAsmParser::
3484cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3485 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3486 // Create a writeback register dummy placeholder.
3487 Inst.addOperand(MCOperand::CreateImm(0));
3488 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3489 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3490 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3491 return true;
3492}
3493
Jim Grosbach7ce05792011-08-03 23:50:40 +00003494/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3495/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3496/// when they refer multiple MIOperands inside a single one.
3497bool ARMAsmParser::
3498cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3499 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3500 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003501 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003502 // Create a writeback register dummy placeholder.
3503 Inst.addOperand(MCOperand::CreateImm(0));
3504 // addr
3505 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3506 // offset
3507 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3508 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003509 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3510 return true;
3511}
3512
Jim Grosbach7ce05792011-08-03 23:50:40 +00003513/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003514/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3515/// when they refer multiple MIOperands inside a single one.
3516bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003517cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3518 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3519 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003520 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003521 // Create a writeback register dummy placeholder.
3522 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003523 // addr
3524 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3525 // offset
3526 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3527 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003528 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3529 return true;
3530}
3531
Jim Grosbach7ce05792011-08-03 23:50:40 +00003532/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003533/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3534/// when they refer multiple MIOperands inside a single one.
3535bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003536cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3537 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003538 // Create a writeback register dummy placeholder.
3539 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003540 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003541 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003542 // addr
3543 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3544 // offset
3545 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3546 // pred
3547 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3548 return true;
3549}
3550
3551/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3552/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3553/// when they refer multiple MIOperands inside a single one.
3554bool ARMAsmParser::
3555cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3556 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3557 // Create a writeback register dummy placeholder.
3558 Inst.addOperand(MCOperand::CreateImm(0));
3559 // Rt
3560 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3561 // addr
3562 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3563 // offset
3564 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3565 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003566 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3567 return true;
3568}
3569
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003570/// cvtLdrdPre - Convert parsed operands to MCInst.
3571/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3572/// when they refer multiple MIOperands inside a single one.
3573bool ARMAsmParser::
3574cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3575 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3576 // Rt, Rt2
3577 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3578 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3579 // Create a writeback register dummy placeholder.
3580 Inst.addOperand(MCOperand::CreateImm(0));
3581 // addr
3582 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3583 // pred
3584 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3585 return true;
3586}
3587
Jim Grosbach14605d12011-08-11 20:28:23 +00003588/// cvtStrdPre - Convert parsed operands to MCInst.
3589/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3590/// when they refer multiple MIOperands inside a single one.
3591bool ARMAsmParser::
3592cvtStrdPre(MCInst &Inst, unsigned Opcode,
3593 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3594 // Create a writeback register dummy placeholder.
3595 Inst.addOperand(MCOperand::CreateImm(0));
3596 // Rt, Rt2
3597 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3598 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3599 // addr
3600 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3601 // pred
3602 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3603 return true;
3604}
3605
Jim Grosbach623a4542011-08-10 22:42:16 +00003606/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3607/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3608/// when they refer multiple MIOperands inside a single one.
3609bool ARMAsmParser::
3610cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3611 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3612 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3613 // Create a writeback register dummy placeholder.
3614 Inst.addOperand(MCOperand::CreateImm(0));
3615 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3616 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3617 return true;
3618}
3619
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003620/// cvtThumbMultiple- Convert parsed operands to MCInst.
3621/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3622/// when they refer multiple MIOperands inside a single one.
3623bool ARMAsmParser::
3624cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3625 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3626 // The second source operand must be the same register as the destination
3627 // operand.
3628 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003629 (((ARMOperand*)Operands[3])->getReg() !=
3630 ((ARMOperand*)Operands[5])->getReg()) &&
3631 (((ARMOperand*)Operands[3])->getReg() !=
3632 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003633 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003634 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003635 return false;
3636 }
3637 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3638 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003639 // If we have a three-operand form, make sure to set Rn to be the operand
3640 // that isn't the same as Rd.
3641 unsigned RegOp = 4;
3642 if (Operands.size() == 6 &&
3643 ((ARMOperand*)Operands[4])->getReg() ==
3644 ((ARMOperand*)Operands[3])->getReg())
3645 RegOp = 5;
3646 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3647 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003648 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3649
3650 return true;
3651}
Jim Grosbach623a4542011-08-10 22:42:16 +00003652
Jim Grosbach12431322011-10-24 22:16:58 +00003653bool ARMAsmParser::
3654cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3655 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3656 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003657 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003658 // Create a writeback register dummy placeholder.
3659 Inst.addOperand(MCOperand::CreateImm(0));
3660 // Vn
3661 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3662 // pred
3663 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3664 return true;
3665}
3666
3667bool ARMAsmParser::
3668cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3669 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3670 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003671 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003672 // Create a writeback register dummy placeholder.
3673 Inst.addOperand(MCOperand::CreateImm(0));
3674 // Vn
3675 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3676 // Vm
3677 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3678 // pred
3679 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3680 return true;
3681}
3682
Jim Grosbach4334e032011-10-31 21:50:31 +00003683bool ARMAsmParser::
3684cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3685 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3686 // Create a writeback register dummy placeholder.
3687 Inst.addOperand(MCOperand::CreateImm(0));
3688 // Vn
3689 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3690 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003691 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003692 // pred
3693 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3694 return true;
3695}
3696
3697bool ARMAsmParser::
3698cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3699 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3700 // Create a writeback register dummy placeholder.
3701 Inst.addOperand(MCOperand::CreateImm(0));
3702 // Vn
3703 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3704 // Vm
3705 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3706 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003707 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003708 // pred
3709 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3710 return true;
3711}
3712
Bill Wendlinge7176102010-11-06 22:36:58 +00003713/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003714/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003715bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003716parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003717 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003718 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003719 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003720 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003721 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003722
Sean Callanan18b83232010-01-19 21:44:56 +00003723 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003724 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003725 if (BaseRegNum == -1)
3726 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003727
Daniel Dunbar05710932011-01-18 05:34:17 +00003728 // The next token must either be a comma or a closing bracket.
3729 const AsmToken &Tok = Parser.getTok();
3730 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003731 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003732
Jim Grosbach7ce05792011-08-03 23:50:40 +00003733 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003734 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003735 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003736
Jim Grosbach7ce05792011-08-03 23:50:40 +00003737 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003738 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003739
Jim Grosbachfb12f352011-09-19 18:42:21 +00003740 // If there's a pre-indexing writeback marker, '!', just add it as a token
3741 // operand. It's rather odd, but syntactically valid.
3742 if (Parser.getTok().is(AsmToken::Exclaim)) {
3743 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3744 Parser.Lex(); // Eat the '!'.
3745 }
3746
Jim Grosbach7ce05792011-08-03 23:50:40 +00003747 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003748 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003749
Jim Grosbach7ce05792011-08-03 23:50:40 +00003750 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3751 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003752
Jim Grosbach57dcb852011-10-11 17:29:55 +00003753 // If we have a ':', it's an alignment specifier.
3754 if (Parser.getTok().is(AsmToken::Colon)) {
3755 Parser.Lex(); // Eat the ':'.
3756 E = Parser.getTok().getLoc();
3757
3758 const MCExpr *Expr;
3759 if (getParser().ParseExpression(Expr))
3760 return true;
3761
3762 // The expression has to be a constant. Memory references with relocations
3763 // don't come through here, as they use the <label> forms of the relevant
3764 // instructions.
3765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3766 if (!CE)
3767 return Error (E, "constant expression expected");
3768
3769 unsigned Align = 0;
3770 switch (CE->getValue()) {
3771 default:
3772 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3773 case 64: Align = 8; break;
3774 case 128: Align = 16; break;
3775 case 256: Align = 32; break;
3776 }
3777
3778 // Now we should have the closing ']'
3779 E = Parser.getTok().getLoc();
3780 if (Parser.getTok().isNot(AsmToken::RBrac))
3781 return Error(E, "']' expected");
3782 Parser.Lex(); // Eat right bracket token.
3783
3784 // Don't worry about range checking the value here. That's handled by
3785 // the is*() predicates.
3786 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3787 ARM_AM::no_shift, 0, Align,
3788 false, S, E));
3789
3790 // If there's a pre-indexing writeback marker, '!', just add it as a token
3791 // operand.
3792 if (Parser.getTok().is(AsmToken::Exclaim)) {
3793 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3794 Parser.Lex(); // Eat the '!'.
3795 }
3796
3797 return false;
3798 }
3799
3800 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003801 // offset. Be friendly and also accept a plain integer (without a leading
3802 // hash) for gas compatibility.
3803 if (Parser.getTok().is(AsmToken::Hash) ||
3804 Parser.getTok().is(AsmToken::Integer)) {
3805 if (Parser.getTok().is(AsmToken::Hash))
3806 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003807 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003808
Owen Anderson0da10cf2011-08-29 19:36:44 +00003809 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003810 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003811 if (getParser().ParseExpression(Offset))
3812 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003813
3814 // The expression has to be a constant. Memory references with relocations
3815 // don't come through here, as they use the <label> forms of the relevant
3816 // instructions.
3817 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3818 if (!CE)
3819 return Error (E, "constant expression expected");
3820
Owen Anderson0da10cf2011-08-29 19:36:44 +00003821 // If the constant was #-0, represent it as INT32_MIN.
3822 int32_t Val = CE->getValue();
3823 if (isNegative && Val == 0)
3824 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3825
Jim Grosbach7ce05792011-08-03 23:50:40 +00003826 // Now we should have the closing ']'
3827 E = Parser.getTok().getLoc();
3828 if (Parser.getTok().isNot(AsmToken::RBrac))
3829 return Error(E, "']' expected");
3830 Parser.Lex(); // Eat right bracket token.
3831
3832 // Don't worry about range checking the value here. That's handled by
3833 // the is*() predicates.
3834 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003835 ARM_AM::no_shift, 0, 0,
3836 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003837
3838 // If there's a pre-indexing writeback marker, '!', just add it as a token
3839 // operand.
3840 if (Parser.getTok().is(AsmToken::Exclaim)) {
3841 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3842 Parser.Lex(); // Eat the '!'.
3843 }
3844
3845 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003846 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003847
3848 // The register offset is optionally preceded by a '+' or '-'
3849 bool isNegative = false;
3850 if (Parser.getTok().is(AsmToken::Minus)) {
3851 isNegative = true;
3852 Parser.Lex(); // Eat the '-'.
3853 } else if (Parser.getTok().is(AsmToken::Plus)) {
3854 // Nothing to do.
3855 Parser.Lex(); // Eat the '+'.
3856 }
3857
3858 E = Parser.getTok().getLoc();
3859 int OffsetRegNum = tryParseRegister();
3860 if (OffsetRegNum == -1)
3861 return Error(E, "register expected");
3862
3863 // If there's a shift operator, handle it.
3864 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003865 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003866 if (Parser.getTok().is(AsmToken::Comma)) {
3867 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003868 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003869 return true;
3870 }
3871
3872 // Now we should have the closing ']'
3873 E = Parser.getTok().getLoc();
3874 if (Parser.getTok().isNot(AsmToken::RBrac))
3875 return Error(E, "']' expected");
3876 Parser.Lex(); // Eat right bracket token.
3877
3878 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003879 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003880 S, E));
3881
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003882 // If there's a pre-indexing writeback marker, '!', just add it as a token
3883 // operand.
3884 if (Parser.getTok().is(AsmToken::Exclaim)) {
3885 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3886 Parser.Lex(); // Eat the '!'.
3887 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003888
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003889 return false;
3890}
3891
Jim Grosbach7ce05792011-08-03 23:50:40 +00003892/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003893/// ( lsl | lsr | asr | ror ) , # shift_amount
3894/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003895/// return true if it parses a shift otherwise it returns false.
3896bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3897 unsigned &Amount) {
3898 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003899 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003900 if (Tok.isNot(AsmToken::Identifier))
3901 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003902 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003903 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003904 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003905 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003906 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003907 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003908 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003909 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003910 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003911 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003912 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003913 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003914 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003915 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003916
Jim Grosbach7ce05792011-08-03 23:50:40 +00003917 // rrx stands alone.
3918 Amount = 0;
3919 if (St != ARM_AM::rrx) {
3920 Loc = Parser.getTok().getLoc();
3921 // A '#' and a shift amount.
3922 const AsmToken &HashTok = Parser.getTok();
3923 if (HashTok.isNot(AsmToken::Hash))
3924 return Error(HashTok.getLoc(), "'#' expected");
3925 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003926
Jim Grosbach7ce05792011-08-03 23:50:40 +00003927 const MCExpr *Expr;
3928 if (getParser().ParseExpression(Expr))
3929 return true;
3930 // Range check the immediate.
3931 // lsl, ror: 0 <= imm <= 31
3932 // lsr, asr: 0 <= imm <= 32
3933 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3934 if (!CE)
3935 return Error(Loc, "shift amount must be an immediate");
3936 int64_t Imm = CE->getValue();
3937 if (Imm < 0 ||
3938 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3939 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3940 return Error(Loc, "immediate shift value out of range");
3941 Amount = Imm;
3942 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003943
3944 return false;
3945}
3946
Jim Grosbach9d390362011-10-03 23:38:36 +00003947/// parseFPImm - A floating point immediate expression operand.
3948ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3949parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3950 SMLoc S = Parser.getTok().getLoc();
3951
3952 if (Parser.getTok().isNot(AsmToken::Hash))
3953 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003954
3955 // Disambiguate the VMOV forms that can accept an FP immediate.
3956 // vmov.f32 <sreg>, #imm
3957 // vmov.f64 <dreg>, #imm
3958 // vmov.f32 <dreg>, #imm @ vector f32x2
3959 // vmov.f32 <qreg>, #imm @ vector f32x4
3960 //
3961 // There are also the NEON VMOV instructions which expect an
3962 // integer constant. Make sure we don't try to parse an FPImm
3963 // for these:
3964 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3965 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3966 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3967 TyOp->getToken() != ".f64"))
3968 return MatchOperand_NoMatch;
3969
Jim Grosbach9d390362011-10-03 23:38:36 +00003970 Parser.Lex(); // Eat the '#'.
3971
3972 // Handle negation, as that still comes through as a separate token.
3973 bool isNegative = false;
3974 if (Parser.getTok().is(AsmToken::Minus)) {
3975 isNegative = true;
3976 Parser.Lex();
3977 }
3978 const AsmToken &Tok = Parser.getTok();
3979 if (Tok.is(AsmToken::Real)) {
3980 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3981 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3982 // If we had a '-' in front, toggle the sign bit.
3983 IntVal ^= (uint64_t)isNegative << 63;
3984 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3985 Parser.Lex(); // Eat the token.
3986 if (Val == -1) {
3987 TokError("floating point value out of range");
3988 return MatchOperand_ParseFail;
3989 }
3990 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3991 return MatchOperand_Success;
3992 }
3993 if (Tok.is(AsmToken::Integer)) {
3994 int64_t Val = Tok.getIntVal();
3995 Parser.Lex(); // Eat the token.
3996 if (Val > 255 || Val < 0) {
3997 TokError("encoded floating point value out of range");
3998 return MatchOperand_ParseFail;
3999 }
4000 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4001 return MatchOperand_Success;
4002 }
4003
4004 TokError("invalid floating point immediate");
4005 return MatchOperand_ParseFail;
4006}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004007/// Parse a arm instruction operand. For now this parses the operand regardless
4008/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004009bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004010 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004011 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004012
4013 // Check if the current operand has a custom associated parser, if so, try to
4014 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004015 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4016 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004017 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004018 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4019 // there was a match, but an error occurred, in which case, just return that
4020 // the operand parsing failed.
4021 if (ResTy == MatchOperand_ParseFail)
4022 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004023
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004024 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004025 default:
4026 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004027 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004028 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004029 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004030 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004031 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004032 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004033 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004034 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004035 else if (Res == -1) // irrecoverable error
4036 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004037 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4038 S = Parser.getTok().getLoc();
4039 Parser.Lex();
4040 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4041 return false;
4042 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004043
4044 // Fall though for the Identifier case that is not a register or a
4045 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004046 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004047 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004048 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004049 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004050 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004051 // This was not a register so parse other operands that start with an
4052 // identifier (like labels) as expressions and create them as immediates.
4053 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004054 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004055 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004056 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004057 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004058 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4059 return false;
4060 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004061 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004062 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004063 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004064 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004065 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004066 // #42 -> immediate.
4067 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004068 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004069 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004070 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004071 const MCExpr *ImmVal;
4072 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004073 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004074 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004075 if (CE) {
4076 int32_t Val = CE->getValue();
4077 if (isNegative && Val == 0)
4078 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004079 }
Sean Callanan76264762010-04-02 22:27:05 +00004080 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004081 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4082 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004083 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004084 case AsmToken::Colon: {
4085 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004086 // FIXME: Check it's an expression prefix,
4087 // e.g. (FOO - :lower16:BAR) isn't legal.
4088 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004089 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004090 return true;
4091
Evan Cheng75972122011-01-13 07:58:56 +00004092 const MCExpr *SubExprVal;
4093 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004094 return true;
4095
Evan Cheng75972122011-01-13 07:58:56 +00004096 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4097 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004098 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004099 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004100 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004101 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004102 }
4103}
4104
Jim Grosbach1355cf12011-07-26 17:10:22 +00004105// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004106// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004107bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004108 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004109
4110 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004111 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004112 Parser.Lex(); // Eat ':'
4113
4114 if (getLexer().isNot(AsmToken::Identifier)) {
4115 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4116 return true;
4117 }
4118
4119 StringRef IDVal = Parser.getTok().getIdentifier();
4120 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004121 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004122 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004123 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004124 } else {
4125 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4126 return true;
4127 }
4128 Parser.Lex();
4129
4130 if (getLexer().isNot(AsmToken::Colon)) {
4131 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4132 return true;
4133 }
4134 Parser.Lex(); // Eat the last ':'
4135 return false;
4136}
4137
Daniel Dunbar352e1482011-01-11 15:59:50 +00004138/// \brief Given a mnemonic, split out possible predication code and carry
4139/// setting letters to form a canonical mnemonic and flags.
4140//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004141// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004142// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004143StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004144 unsigned &PredicationCode,
4145 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004146 unsigned &ProcessorIMod,
4147 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004148 PredicationCode = ARMCC::AL;
4149 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004150 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004151
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004152 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004153 //
4154 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004155 if ((Mnemonic == "movs" && isThumb()) ||
4156 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4157 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4158 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4159 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4160 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4161 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4162 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004163 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004164
Jim Grosbach3f00e312011-07-11 17:09:57 +00004165 // First, split out any predication code. Ignore mnemonics we know aren't
4166 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004167 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004168 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004169 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004170 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004171 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4172 .Case("eq", ARMCC::EQ)
4173 .Case("ne", ARMCC::NE)
4174 .Case("hs", ARMCC::HS)
4175 .Case("cs", ARMCC::HS)
4176 .Case("lo", ARMCC::LO)
4177 .Case("cc", ARMCC::LO)
4178 .Case("mi", ARMCC::MI)
4179 .Case("pl", ARMCC::PL)
4180 .Case("vs", ARMCC::VS)
4181 .Case("vc", ARMCC::VC)
4182 .Case("hi", ARMCC::HI)
4183 .Case("ls", ARMCC::LS)
4184 .Case("ge", ARMCC::GE)
4185 .Case("lt", ARMCC::LT)
4186 .Case("gt", ARMCC::GT)
4187 .Case("le", ARMCC::LE)
4188 .Case("al", ARMCC::AL)
4189 .Default(~0U);
4190 if (CC != ~0U) {
4191 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4192 PredicationCode = CC;
4193 }
Bill Wendling52925b62010-10-29 23:50:21 +00004194 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004195
Daniel Dunbar352e1482011-01-11 15:59:50 +00004196 // Next, determine if we have a carry setting bit. We explicitly ignore all
4197 // the instructions we know end in 's'.
4198 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004199 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004200 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4201 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4202 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004203 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4204 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004205 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4206 CarrySetting = true;
4207 }
4208
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004209 // The "cps" instruction can have a interrupt mode operand which is glued into
4210 // the mnemonic. Check if this is the case, split it and parse the imod op
4211 if (Mnemonic.startswith("cps")) {
4212 // Split out any imod code.
4213 unsigned IMod =
4214 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4215 .Case("ie", ARM_PROC::IE)
4216 .Case("id", ARM_PROC::ID)
4217 .Default(~0U);
4218 if (IMod != ~0U) {
4219 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4220 ProcessorIMod = IMod;
4221 }
4222 }
4223
Jim Grosbach89df9962011-08-26 21:43:41 +00004224 // The "it" instruction has the condition mask on the end of the mnemonic.
4225 if (Mnemonic.startswith("it")) {
4226 ITMask = Mnemonic.slice(2, Mnemonic.size());
4227 Mnemonic = Mnemonic.slice(0, 2);
4228 }
4229
Daniel Dunbar352e1482011-01-11 15:59:50 +00004230 return Mnemonic;
4231}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004232
4233/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4234/// inclusion of carry set or predication code operands.
4235//
4236// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004237void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004238getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004239 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004240 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4241 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004242 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004243 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004244 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004245 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004246 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004247 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004248 Mnemonic == "mla" || Mnemonic == "smlal" ||
4249 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004250 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004251 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004252 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004253
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004254 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4255 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4256 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4257 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004258 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4259 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004260 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004261 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4262 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4263 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004264 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4265 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004266 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004267 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004268 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004269 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004270
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004271 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004272 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004273 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004274 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004275 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004276}
4277
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004278bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4279 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004280 // FIXME: This is all horribly hacky. We really need a better way to deal
4281 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004282
4283 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4284 // another does not. Specifically, the MOVW instruction does not. So we
4285 // special case it here and remove the defaulted (non-setting) cc_out
4286 // operand if that's the instruction we're trying to match.
4287 //
4288 // We do this as post-processing of the explicit operands rather than just
4289 // conditionally adding the cc_out in the first place because we need
4290 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004291 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004292 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4293 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4294 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4295 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004296
4297 // Register-register 'add' for thumb does not have a cc_out operand
4298 // when there are only two register operands.
4299 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4300 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4301 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4302 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4303 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004304 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004305 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4306 // have to check the immediate range here since Thumb2 has a variant
4307 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004308 if (((isThumb() && Mnemonic == "add") ||
4309 (isThumbTwo() && Mnemonic == "sub")) &&
4310 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004311 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4312 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4313 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004314 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4315 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4316 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004317 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004318 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4319 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004320 // selecting via the generic "add" mnemonic, so to know that we
4321 // should remove the cc_out operand, we have to explicitly check that
4322 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004323 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4324 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004325 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4326 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4327 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4328 // Nest conditions rather than one big 'if' statement for readability.
4329 //
4330 // If either register is a high reg, it's either one of the SP
4331 // variants (handled above) or a 32-bit encoding, so we just
4332 // check against T3.
4333 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4334 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4335 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4336 return false;
4337 // If both registers are low, we're in an IT block, and the immediate is
4338 // in range, we should use encoding T1 instead, which has a cc_out.
4339 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004340 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004341 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4342 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4343 return false;
4344
4345 // Otherwise, we use encoding T4, which does not have a cc_out
4346 // operand.
4347 return true;
4348 }
4349
Jim Grosbach64944f42011-09-14 21:00:40 +00004350 // The thumb2 multiply instruction doesn't have a CCOut register, so
4351 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4352 // use the 16-bit encoding or not.
4353 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4354 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4355 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4356 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4357 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4358 // If the registers aren't low regs, the destination reg isn't the
4359 // same as one of the source regs, or the cc_out operand is zero
4360 // outside of an IT block, we have to use the 32-bit encoding, so
4361 // remove the cc_out operand.
4362 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4363 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004364 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004365 !inITBlock() ||
4366 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4367 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4368 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4369 static_cast<ARMOperand*>(Operands[4])->getReg())))
4370 return true;
4371
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004372 // Also check the 'mul' syntax variant that doesn't specify an explicit
4373 // destination register.
4374 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4375 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4376 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4377 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4378 // If the registers aren't low regs or the cc_out operand is zero
4379 // outside of an IT block, we have to use the 32-bit encoding, so
4380 // remove the cc_out operand.
4381 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4382 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4383 !inITBlock()))
4384 return true;
4385
Jim Grosbach64944f42011-09-14 21:00:40 +00004386
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004387
Jim Grosbachf69c8042011-08-24 21:42:27 +00004388 // Register-register 'add/sub' for thumb does not have a cc_out operand
4389 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4390 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4391 // right, this will result in better diagnostics (which operand is off)
4392 // anyway.
4393 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4394 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004395 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4396 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4397 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4398 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004399
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004400 return false;
4401}
4402
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004403static bool isDataTypeToken(StringRef Tok) {
4404 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4405 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4406 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4407 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4408 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4409 Tok == ".f" || Tok == ".d";
4410}
4411
4412// FIXME: This bit should probably be handled via an explicit match class
4413// in the .td files that matches the suffix instead of having it be
4414// a literal string token the way it is now.
4415static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4416 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4417}
4418
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004419/// Parse an arm instruction mnemonic followed by its operands.
4420bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4421 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4422 // Create the leading tokens for the mnemonic, split by '.' characters.
4423 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004424 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004425
Daniel Dunbar352e1482011-01-11 15:59:50 +00004426 // Split out the predication code and carry setting flag from the mnemonic.
4427 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004428 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004429 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004430 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004431 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004432 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004433
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004434 // In Thumb1, only the branch (B) instruction can be predicated.
4435 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4436 Parser.EatToEndOfStatement();
4437 return Error(NameLoc, "conditional execution not supported in Thumb1");
4438 }
4439
Jim Grosbachffa32252011-07-19 19:13:28 +00004440 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4441
Jim Grosbach89df9962011-08-26 21:43:41 +00004442 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4443 // is the mask as it will be for the IT encoding if the conditional
4444 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4445 // where the conditional bit0 is zero, the instruction post-processing
4446 // will adjust the mask accordingly.
4447 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004448 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4449 if (ITMask.size() > 3) {
4450 Parser.EatToEndOfStatement();
4451 return Error(Loc, "too many conditions on IT instruction");
4452 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004453 unsigned Mask = 8;
4454 for (unsigned i = ITMask.size(); i != 0; --i) {
4455 char pos = ITMask[i - 1];
4456 if (pos != 't' && pos != 'e') {
4457 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004458 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004459 }
4460 Mask >>= 1;
4461 if (ITMask[i - 1] == 't')
4462 Mask |= 8;
4463 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004464 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004465 }
4466
Jim Grosbachffa32252011-07-19 19:13:28 +00004467 // FIXME: This is all a pretty gross hack. We should automatically handle
4468 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004469
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004470 // Next, add the CCOut and ConditionCode operands, if needed.
4471 //
4472 // For mnemonics which can ever incorporate a carry setting bit or predication
4473 // code, our matching model involves us always generating CCOut and
4474 // ConditionCode operands to match the mnemonic "as written" and then we let
4475 // the matcher deal with finding the right instruction or generating an
4476 // appropriate error.
4477 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004478 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004479
Jim Grosbach33c16a22011-07-14 22:04:21 +00004480 // If we had a carry-set on an instruction that can't do that, issue an
4481 // error.
4482 if (!CanAcceptCarrySet && CarrySetting) {
4483 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004484 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004485 "' can not set flags, but 's' suffix specified");
4486 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004487 // If we had a predication code on an instruction that can't do that, issue an
4488 // error.
4489 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4490 Parser.EatToEndOfStatement();
4491 return Error(NameLoc, "instruction '" + Mnemonic +
4492 "' is not predicable, but condition code specified");
4493 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004494
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004495 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004496 if (CanAcceptCarrySet) {
4497 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004498 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004499 Loc));
4500 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004501
4502 // Add the predication code operand, if necessary.
4503 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004504 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4505 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004506 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004507 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004508 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004509
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004510 // Add the processor imod operand, if necessary.
4511 if (ProcessorIMod) {
4512 Operands.push_back(ARMOperand::CreateImm(
4513 MCConstantExpr::Create(ProcessorIMod, getContext()),
4514 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004515 }
4516
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004517 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004518 while (Next != StringRef::npos) {
4519 Start = Next;
4520 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004521 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004522
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004523 // Some NEON instructions have an optional datatype suffix that is
4524 // completely ignored. Check for that.
4525 if (isDataTypeToken(ExtraToken) &&
4526 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4527 continue;
4528
Jim Grosbach81d2e392011-09-07 16:06:04 +00004529 if (ExtraToken != ".n") {
4530 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4531 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4532 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004533 }
4534
4535 // Read the remaining operands.
4536 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004537 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004538 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004539 Parser.EatToEndOfStatement();
4540 return true;
4541 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004542
4543 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004544 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004545
4546 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004547 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004548 Parser.EatToEndOfStatement();
4549 return true;
4550 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004551 }
4552 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004553
Chris Lattnercbf8a982010-09-11 16:18:25 +00004554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004555 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004556 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004557 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004558 }
Bill Wendling146018f2010-11-06 21:42:12 +00004559
Chris Lattner34e53142010-09-08 05:10:46 +00004560 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004561
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004562 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4563 // do and don't have a cc_out optional-def operand. With some spot-checks
4564 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004565 // parse and adjust accordingly before actually matching. We shouldn't ever
4566 // try to remove a cc_out operand that was explicitly set on the the
4567 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4568 // table driven matcher doesn't fit well with the ARM instruction set.
4569 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004570 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4571 Operands.erase(Operands.begin() + 1);
4572 delete Op;
4573 }
4574
Jim Grosbachcf121c32011-07-28 21:57:55 +00004575 // ARM mode 'blx' need special handling, as the register operand version
4576 // is predicable, but the label operand version is not. So, we can't rely
4577 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004578 // a k_CondCode operand in the list. If we're trying to match the label
4579 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004580 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4581 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4582 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4583 Operands.erase(Operands.begin() + 1);
4584 delete Op;
4585 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004586
4587 // The vector-compare-to-zero instructions have a literal token "#0" at
4588 // the end that comes to here as an immediate operand. Convert it to a
4589 // token to play nicely with the matcher.
4590 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4591 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4592 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4593 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4595 if (CE && CE->getValue() == 0) {
4596 Operands.erase(Operands.begin() + 5);
4597 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4598 delete Op;
4599 }
4600 }
Jim Grosbach68259142011-10-03 22:30:24 +00004601 // VCMP{E} does the same thing, but with a different operand count.
4602 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4603 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4604 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4606 if (CE && CE->getValue() == 0) {
4607 Operands.erase(Operands.begin() + 4);
4608 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4609 delete Op;
4610 }
4611 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004612 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4613 // end. Convert it to a token here.
4614 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4615 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4616 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4618 if (CE && CE->getValue() == 0) {
4619 Operands.erase(Operands.begin() + 5);
4620 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4621 delete Op;
4622 }
4623 }
4624
Chris Lattner98986712010-01-14 22:21:20 +00004625 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004626}
4627
Jim Grosbach189610f2011-07-26 18:25:39 +00004628// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004629
4630// return 'true' if register list contains non-low GPR registers,
4631// 'false' otherwise. If Reg is in the register list or is HiReg, set
4632// 'containsReg' to true.
4633static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4634 unsigned HiReg, bool &containsReg) {
4635 containsReg = false;
4636 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4637 unsigned OpReg = Inst.getOperand(i).getReg();
4638 if (OpReg == Reg)
4639 containsReg = true;
4640 // Anything other than a low register isn't legal here.
4641 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4642 return true;
4643 }
4644 return false;
4645}
4646
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004647// Check if the specified regisgter is in the register list of the inst,
4648// starting at the indicated operand number.
4649static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4650 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4651 unsigned OpReg = Inst.getOperand(i).getReg();
4652 if (OpReg == Reg)
4653 return true;
4654 }
4655 return false;
4656}
4657
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004658// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4659// the ARMInsts array) instead. Getting that here requires awkward
4660// API changes, though. Better way?
4661namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004662extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004663}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004664static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004665 return ARMInsts[Opcode];
4666}
4667
Jim Grosbach189610f2011-07-26 18:25:39 +00004668// FIXME: We would really like to be able to tablegen'erate this.
4669bool ARMAsmParser::
4670validateInstruction(MCInst &Inst,
4671 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004672 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004673 SMLoc Loc = Operands[0]->getStartLoc();
4674 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004675 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4676 // being allowed in IT blocks, but not being predicable. It just always
4677 // executes.
4678 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004679 unsigned bit = 1;
4680 if (ITState.FirstCond)
4681 ITState.FirstCond = false;
4682 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004683 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004684 // The instruction must be predicable.
4685 if (!MCID.isPredicable())
4686 return Error(Loc, "instructions in IT block must be predicable");
4687 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4688 unsigned ITCond = bit ? ITState.Cond :
4689 ARMCC::getOppositeCondition(ITState.Cond);
4690 if (Cond != ITCond) {
4691 // Find the condition code Operand to get its SMLoc information.
4692 SMLoc CondLoc;
4693 for (unsigned i = 1; i < Operands.size(); ++i)
4694 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4695 CondLoc = Operands[i]->getStartLoc();
4696 return Error(CondLoc, "incorrect condition in IT block; got '" +
4697 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4698 "', but expected '" +
4699 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4700 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004701 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004702 } else if (isThumbTwo() && MCID.isPredicable() &&
4703 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004704 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4705 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004706 return Error(Loc, "predicated instructions must be in IT block");
4707
Jim Grosbach189610f2011-07-26 18:25:39 +00004708 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004709 case ARM::LDRD:
4710 case ARM::LDRD_PRE:
4711 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004712 case ARM::LDREXD: {
4713 // Rt2 must be Rt + 1.
4714 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4715 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4716 if (Rt2 != Rt + 1)
4717 return Error(Operands[3]->getStartLoc(),
4718 "destination operands must be sequential");
4719 return false;
4720 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004721 case ARM::STRD: {
4722 // Rt2 must be Rt + 1.
4723 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4724 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4725 if (Rt2 != Rt + 1)
4726 return Error(Operands[3]->getStartLoc(),
4727 "source operands must be sequential");
4728 return false;
4729 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004730 case ARM::STRD_PRE:
4731 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004732 case ARM::STREXD: {
4733 // Rt2 must be Rt + 1.
4734 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4735 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4736 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004737 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004738 "source operands must be sequential");
4739 return false;
4740 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004741 case ARM::SBFX:
4742 case ARM::UBFX: {
4743 // width must be in range [1, 32-lsb]
4744 unsigned lsb = Inst.getOperand(2).getImm();
4745 unsigned widthm1 = Inst.getOperand(3).getImm();
4746 if (widthm1 >= 32 - lsb)
4747 return Error(Operands[5]->getStartLoc(),
4748 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004749 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004750 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004751 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004752 // If we're parsing Thumb2, the .w variant is available and handles
4753 // most cases that are normally illegal for a Thumb1 LDM
4754 // instruction. We'll make the transformation in processInstruction()
4755 // if necessary.
4756 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004757 // Thumb LDM instructions are writeback iff the base register is not
4758 // in the register list.
4759 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004760 bool hasWritebackToken =
4761 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4762 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004763 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004764 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004765 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4766 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004767 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004768 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004769 return Error(Operands[2]->getStartLoc(),
4770 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004771 // If we should not have writeback, there must not be a '!'. This is
4772 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004773 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004774 return Error(Operands[3]->getStartLoc(),
4775 "writeback operator '!' not allowed when base register "
4776 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004777
4778 break;
4779 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004780 case ARM::t2LDMIA_UPD: {
4781 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4782 return Error(Operands[4]->getStartLoc(),
4783 "writeback operator '!' not allowed when base register "
4784 "in register list");
4785 break;
4786 }
Jim Grosbach54026372011-11-10 23:17:11 +00004787 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4788 // so only issue a diagnostic for thumb1. The instructions will be
4789 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004790 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004791 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004792 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4793 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004794 return Error(Operands[2]->getStartLoc(),
4795 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004796 break;
4797 }
4798 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004799 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004800 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4801 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004802 return Error(Operands[2]->getStartLoc(),
4803 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004804 break;
4805 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004806 case ARM::tSTMIA_UPD: {
4807 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004808 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004809 return Error(Operands[4]->getStartLoc(),
4810 "registers must be in range r0-r7");
4811 break;
4812 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004813 }
4814
4815 return false;
4816}
4817
Jim Grosbach84defb52011-12-02 22:34:51 +00004818static unsigned getRealVSTLNOpcode(unsigned Opc) {
4819 switch(Opc) {
4820 default: assert(0 && "unexpected opcode!");
4821 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4822 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4823 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4824 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4825 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4826 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4827 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4828 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4829 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4830 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4831 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4832 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4833 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4834 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4835 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4836 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4837 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4838 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4839 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4840 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4841 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4842 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4843 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4844 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4845 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4846 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4847 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4848 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4849 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4850 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4851 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4852 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4853 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4854 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4855 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4856 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4857 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4858 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4859 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4860 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4861 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4862 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4863 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4864 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4865 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4866 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4867 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4868 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4869 }
4870}
4871
4872static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004873 switch(Opc) {
4874 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00004875 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4876 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4877 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4878 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4879 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4880 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4881 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4882 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
4883 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
4884 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
4885 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
4886 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
4887 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
4888 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
4889 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
4890 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
4891 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
4892 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
4893 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
4894 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
4895 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
4896 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
4897 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
4898 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
4899 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
4900 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
4901 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
4902 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
4903 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
4904 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
4905 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
4906 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004907 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4908 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4909 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4910 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4911 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00004912 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4913 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4914 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4915 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4916 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004917 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4918 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4919 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4920 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4921 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4922 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004923 }
4924}
4925
Jim Grosbach83ec8772011-11-10 23:42:14 +00004926bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004927processInstruction(MCInst &Inst,
4928 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4929 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00004930 // Handle NEON VST1 complex aliases.
4931 case ARM::VST1LNdWB_register_Asm_8:
4932 case ARM::VST1LNdWB_register_Asm_P8:
4933 case ARM::VST1LNdWB_register_Asm_I8:
4934 case ARM::VST1LNdWB_register_Asm_S8:
4935 case ARM::VST1LNdWB_register_Asm_U8:
4936 case ARM::VST1LNdWB_register_Asm_16:
4937 case ARM::VST1LNdWB_register_Asm_P16:
4938 case ARM::VST1LNdWB_register_Asm_I16:
4939 case ARM::VST1LNdWB_register_Asm_S16:
4940 case ARM::VST1LNdWB_register_Asm_U16:
4941 case ARM::VST1LNdWB_register_Asm_32:
4942 case ARM::VST1LNdWB_register_Asm_F:
4943 case ARM::VST1LNdWB_register_Asm_F32:
4944 case ARM::VST1LNdWB_register_Asm_I32:
4945 case ARM::VST1LNdWB_register_Asm_S32:
4946 case ARM::VST1LNdWB_register_Asm_U32: {
4947 MCInst TmpInst;
4948 // Shuffle the operands around so the lane index operand is in the
4949 // right place.
4950 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4951 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4952 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4953 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4954 TmpInst.addOperand(Inst.getOperand(4)); // Rm
4955 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4956 TmpInst.addOperand(Inst.getOperand(1)); // lane
4957 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
4958 TmpInst.addOperand(Inst.getOperand(6));
4959 Inst = TmpInst;
4960 return true;
4961 }
4962 case ARM::VST1LNdWB_fixed_Asm_8:
4963 case ARM::VST1LNdWB_fixed_Asm_P8:
4964 case ARM::VST1LNdWB_fixed_Asm_I8:
4965 case ARM::VST1LNdWB_fixed_Asm_S8:
4966 case ARM::VST1LNdWB_fixed_Asm_U8:
4967 case ARM::VST1LNdWB_fixed_Asm_16:
4968 case ARM::VST1LNdWB_fixed_Asm_P16:
4969 case ARM::VST1LNdWB_fixed_Asm_I16:
4970 case ARM::VST1LNdWB_fixed_Asm_S16:
4971 case ARM::VST1LNdWB_fixed_Asm_U16:
4972 case ARM::VST1LNdWB_fixed_Asm_32:
4973 case ARM::VST1LNdWB_fixed_Asm_F:
4974 case ARM::VST1LNdWB_fixed_Asm_F32:
4975 case ARM::VST1LNdWB_fixed_Asm_I32:
4976 case ARM::VST1LNdWB_fixed_Asm_S32:
4977 case ARM::VST1LNdWB_fixed_Asm_U32: {
4978 MCInst TmpInst;
4979 // Shuffle the operands around so the lane index operand is in the
4980 // right place.
4981 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4982 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4983 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4984 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4985 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
4986 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4987 TmpInst.addOperand(Inst.getOperand(1)); // lane
4988 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
4989 TmpInst.addOperand(Inst.getOperand(5));
4990 Inst = TmpInst;
4991 return true;
4992 }
4993 case ARM::VST1LNdAsm_8:
4994 case ARM::VST1LNdAsm_P8:
4995 case ARM::VST1LNdAsm_I8:
4996 case ARM::VST1LNdAsm_S8:
4997 case ARM::VST1LNdAsm_U8:
4998 case ARM::VST1LNdAsm_16:
4999 case ARM::VST1LNdAsm_P16:
5000 case ARM::VST1LNdAsm_I16:
5001 case ARM::VST1LNdAsm_S16:
5002 case ARM::VST1LNdAsm_U16:
5003 case ARM::VST1LNdAsm_32:
5004 case ARM::VST1LNdAsm_F:
5005 case ARM::VST1LNdAsm_F32:
5006 case ARM::VST1LNdAsm_I32:
5007 case ARM::VST1LNdAsm_S32:
5008 case ARM::VST1LNdAsm_U32: {
5009 MCInst TmpInst;
5010 // Shuffle the operands around so the lane index operand is in the
5011 // right place.
5012 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5013 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5014 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5015 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5016 TmpInst.addOperand(Inst.getOperand(1)); // lane
5017 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5018 TmpInst.addOperand(Inst.getOperand(5));
5019 Inst = TmpInst;
5020 return true;
5021 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005022 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005023 case ARM::VLD1LNdWB_register_Asm_8:
5024 case ARM::VLD1LNdWB_register_Asm_P8:
5025 case ARM::VLD1LNdWB_register_Asm_I8:
5026 case ARM::VLD1LNdWB_register_Asm_S8:
5027 case ARM::VLD1LNdWB_register_Asm_U8:
5028 case ARM::VLD1LNdWB_register_Asm_16:
5029 case ARM::VLD1LNdWB_register_Asm_P16:
5030 case ARM::VLD1LNdWB_register_Asm_I16:
5031 case ARM::VLD1LNdWB_register_Asm_S16:
5032 case ARM::VLD1LNdWB_register_Asm_U16:
5033 case ARM::VLD1LNdWB_register_Asm_32:
5034 case ARM::VLD1LNdWB_register_Asm_F:
5035 case ARM::VLD1LNdWB_register_Asm_F32:
5036 case ARM::VLD1LNdWB_register_Asm_I32:
5037 case ARM::VLD1LNdWB_register_Asm_S32:
5038 case ARM::VLD1LNdWB_register_Asm_U32: {
5039 MCInst TmpInst;
5040 // Shuffle the operands around so the lane index operand is in the
5041 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005042 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005043 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5044 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5045 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5046 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5047 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5048 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5049 TmpInst.addOperand(Inst.getOperand(1)); // lane
5050 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5051 TmpInst.addOperand(Inst.getOperand(6));
5052 Inst = TmpInst;
5053 return true;
5054 }
5055 case ARM::VLD1LNdWB_fixed_Asm_8:
5056 case ARM::VLD1LNdWB_fixed_Asm_P8:
5057 case ARM::VLD1LNdWB_fixed_Asm_I8:
5058 case ARM::VLD1LNdWB_fixed_Asm_S8:
5059 case ARM::VLD1LNdWB_fixed_Asm_U8:
5060 case ARM::VLD1LNdWB_fixed_Asm_16:
5061 case ARM::VLD1LNdWB_fixed_Asm_P16:
5062 case ARM::VLD1LNdWB_fixed_Asm_I16:
5063 case ARM::VLD1LNdWB_fixed_Asm_S16:
5064 case ARM::VLD1LNdWB_fixed_Asm_U16:
5065 case ARM::VLD1LNdWB_fixed_Asm_32:
5066 case ARM::VLD1LNdWB_fixed_Asm_F:
5067 case ARM::VLD1LNdWB_fixed_Asm_F32:
5068 case ARM::VLD1LNdWB_fixed_Asm_I32:
5069 case ARM::VLD1LNdWB_fixed_Asm_S32:
5070 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5071 MCInst TmpInst;
5072 // Shuffle the operands around so the lane index operand is in the
5073 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005074 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005075 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5076 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5077 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5078 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5079 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5080 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5081 TmpInst.addOperand(Inst.getOperand(1)); // lane
5082 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5083 TmpInst.addOperand(Inst.getOperand(5));
5084 Inst = TmpInst;
5085 return true;
5086 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005087 case ARM::VLD1LNdAsm_8:
5088 case ARM::VLD1LNdAsm_P8:
5089 case ARM::VLD1LNdAsm_I8:
5090 case ARM::VLD1LNdAsm_S8:
5091 case ARM::VLD1LNdAsm_U8:
5092 case ARM::VLD1LNdAsm_16:
5093 case ARM::VLD1LNdAsm_P16:
5094 case ARM::VLD1LNdAsm_I16:
5095 case ARM::VLD1LNdAsm_S16:
5096 case ARM::VLD1LNdAsm_U16:
5097 case ARM::VLD1LNdAsm_32:
5098 case ARM::VLD1LNdAsm_F:
5099 case ARM::VLD1LNdAsm_F32:
5100 case ARM::VLD1LNdAsm_I32:
5101 case ARM::VLD1LNdAsm_S32:
5102 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005103 MCInst TmpInst;
5104 // Shuffle the operands around so the lane index operand is in the
5105 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005106 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005107 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5108 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5109 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5110 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5111 TmpInst.addOperand(Inst.getOperand(1)); // lane
5112 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5113 TmpInst.addOperand(Inst.getOperand(5));
5114 Inst = TmpInst;
5115 return true;
5116 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00005117 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005118 case ARM::ASRr:
5119 case ARM::LSRr:
5120 case ARM::LSLr:
5121 case ARM::RORr: {
5122 ARM_AM::ShiftOpc ShiftTy;
5123 switch(Inst.getOpcode()) {
5124 default: llvm_unreachable("unexpected opcode!");
5125 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5126 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5127 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5128 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5129 }
5130 // A shift by zero is a plain MOVr, not a MOVsi.
5131 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5132 MCInst TmpInst;
5133 TmpInst.setOpcode(ARM::MOVsr);
5134 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5135 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5136 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5137 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5138 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5139 TmpInst.addOperand(Inst.getOperand(4));
5140 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5141 Inst = TmpInst;
5142 return true;
5143 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005144 case ARM::ASRi:
5145 case ARM::LSRi:
5146 case ARM::LSLi:
5147 case ARM::RORi: {
5148 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005149 switch(Inst.getOpcode()) {
5150 default: llvm_unreachable("unexpected opcode!");
5151 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5152 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5153 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5154 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5155 }
5156 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005157 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005158 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5159 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005160 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005161 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005162 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5163 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005164 if (Opc == ARM::MOVsi)
5165 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005166 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5167 TmpInst.addOperand(Inst.getOperand(4));
5168 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5169 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005170 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005171 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005172 case ARM::RRXi: {
5173 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5174 MCInst TmpInst;
5175 TmpInst.setOpcode(ARM::MOVsi);
5176 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5177 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5178 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5179 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5180 TmpInst.addOperand(Inst.getOperand(3));
5181 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5182 Inst = TmpInst;
5183 return true;
5184 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005185 case ARM::t2LDMIA_UPD: {
5186 // If this is a load of a single register, then we should use
5187 // a post-indexed LDR instruction instead, per the ARM ARM.
5188 if (Inst.getNumOperands() != 5)
5189 return false;
5190 MCInst TmpInst;
5191 TmpInst.setOpcode(ARM::t2LDR_POST);
5192 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5193 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5194 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5195 TmpInst.addOperand(MCOperand::CreateImm(4));
5196 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5197 TmpInst.addOperand(Inst.getOperand(3));
5198 Inst = TmpInst;
5199 return true;
5200 }
5201 case ARM::t2STMDB_UPD: {
5202 // If this is a store of a single register, then we should use
5203 // a pre-indexed STR instruction instead, per the ARM ARM.
5204 if (Inst.getNumOperands() != 5)
5205 return false;
5206 MCInst TmpInst;
5207 TmpInst.setOpcode(ARM::t2STR_PRE);
5208 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5209 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5210 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5211 TmpInst.addOperand(MCOperand::CreateImm(-4));
5212 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5213 TmpInst.addOperand(Inst.getOperand(3));
5214 Inst = TmpInst;
5215 return true;
5216 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005217 case ARM::LDMIA_UPD:
5218 // If this is a load of a single register via a 'pop', then we should use
5219 // a post-indexed LDR instruction instead, per the ARM ARM.
5220 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5221 Inst.getNumOperands() == 5) {
5222 MCInst TmpInst;
5223 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5224 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5225 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5226 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5227 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5228 TmpInst.addOperand(MCOperand::CreateImm(4));
5229 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5230 TmpInst.addOperand(Inst.getOperand(3));
5231 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005232 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005233 }
5234 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005235 case ARM::STMDB_UPD:
5236 // If this is a store of a single register via a 'push', then we should use
5237 // a pre-indexed STR instruction instead, per the ARM ARM.
5238 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5239 Inst.getNumOperands() == 5) {
5240 MCInst TmpInst;
5241 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5242 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5243 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5244 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5245 TmpInst.addOperand(MCOperand::CreateImm(-4));
5246 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5247 TmpInst.addOperand(Inst.getOperand(3));
5248 Inst = TmpInst;
5249 }
5250 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005251 case ARM::t2ADDri12:
5252 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5253 // mnemonic was used (not "addw"), encoding T3 is preferred.
5254 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5255 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5256 break;
5257 Inst.setOpcode(ARM::t2ADDri);
5258 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5259 break;
5260 case ARM::t2SUBri12:
5261 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5262 // mnemonic was used (not "subw"), encoding T3 is preferred.
5263 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5264 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5265 break;
5266 Inst.setOpcode(ARM::t2SUBri);
5267 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5268 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005269 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005270 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5271 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5272 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5273 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005274 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005275 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005276 return true;
5277 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005278 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005279 case ARM::tSUBi8:
5280 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5281 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5282 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5283 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005284 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005285 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005286 return true;
5287 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005288 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005289 case ARM::t2ADDrr: {
5290 // If the destination and first source operand are the same, and
5291 // there's no setting of the flags, use encoding T2 instead of T3.
5292 // Note that this is only for ADD, not SUB. This mirrors the system
5293 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5294 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5295 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005296 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5297 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005298 break;
5299 MCInst TmpInst;
5300 TmpInst.setOpcode(ARM::tADDhirr);
5301 TmpInst.addOperand(Inst.getOperand(0));
5302 TmpInst.addOperand(Inst.getOperand(0));
5303 TmpInst.addOperand(Inst.getOperand(2));
5304 TmpInst.addOperand(Inst.getOperand(3));
5305 TmpInst.addOperand(Inst.getOperand(4));
5306 Inst = TmpInst;
5307 return true;
5308 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005309 case ARM::tB:
5310 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005311 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005312 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005313 return true;
5314 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005315 break;
5316 case ARM::t2B:
5317 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005318 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005319 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005320 return true;
5321 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005322 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005323 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005324 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005325 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005326 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005327 return true;
5328 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005329 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005330 case ARM::tBcc:
5331 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005332 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005333 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005334 return true;
5335 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005336 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005337 case ARM::tLDMIA: {
5338 // If the register list contains any high registers, or if the writeback
5339 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5340 // instead if we're in Thumb2. Otherwise, this should have generated
5341 // an error in validateInstruction().
5342 unsigned Rn = Inst.getOperand(0).getReg();
5343 bool hasWritebackToken =
5344 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5345 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5346 bool listContainsBase;
5347 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5348 (!listContainsBase && !hasWritebackToken) ||
5349 (listContainsBase && hasWritebackToken)) {
5350 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5351 assert (isThumbTwo());
5352 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5353 // If we're switching to the updating version, we need to insert
5354 // the writeback tied operand.
5355 if (hasWritebackToken)
5356 Inst.insert(Inst.begin(),
5357 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005358 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005359 }
5360 break;
5361 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005362 case ARM::tSTMIA_UPD: {
5363 // If the register list contains any high registers, we need to use
5364 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5365 // should have generated an error in validateInstruction().
5366 unsigned Rn = Inst.getOperand(0).getReg();
5367 bool listContainsBase;
5368 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5369 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5370 assert (isThumbTwo());
5371 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005372 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005373 }
5374 break;
5375 }
Jim Grosbach54026372011-11-10 23:17:11 +00005376 case ARM::tPOP: {
5377 bool listContainsBase;
5378 // If the register list contains any high registers, we need to use
5379 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5380 // should have generated an error in validateInstruction().
5381 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005382 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005383 assert (isThumbTwo());
5384 Inst.setOpcode(ARM::t2LDMIA_UPD);
5385 // Add the base register and writeback operands.
5386 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5387 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005388 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005389 }
5390 case ARM::tPUSH: {
5391 bool listContainsBase;
5392 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005393 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005394 assert (isThumbTwo());
5395 Inst.setOpcode(ARM::t2STMDB_UPD);
5396 // Add the base register and writeback operands.
5397 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5398 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005399 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005400 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005401 case ARM::t2MOVi: {
5402 // If we can use the 16-bit encoding and the user didn't explicitly
5403 // request the 32-bit variant, transform it here.
5404 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5405 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005406 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5407 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5408 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005409 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5410 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5411 // The operands aren't in the same order for tMOVi8...
5412 MCInst TmpInst;
5413 TmpInst.setOpcode(ARM::tMOVi8);
5414 TmpInst.addOperand(Inst.getOperand(0));
5415 TmpInst.addOperand(Inst.getOperand(4));
5416 TmpInst.addOperand(Inst.getOperand(1));
5417 TmpInst.addOperand(Inst.getOperand(2));
5418 TmpInst.addOperand(Inst.getOperand(3));
5419 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005420 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005421 }
5422 break;
5423 }
5424 case ARM::t2MOVr: {
5425 // If we can use the 16-bit encoding and the user didn't explicitly
5426 // request the 32-bit variant, transform it here.
5427 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5428 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5429 Inst.getOperand(2).getImm() == ARMCC::AL &&
5430 Inst.getOperand(4).getReg() == ARM::CPSR &&
5431 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5432 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5433 // The operands aren't the same for tMOV[S]r... (no cc_out)
5434 MCInst TmpInst;
5435 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5436 TmpInst.addOperand(Inst.getOperand(0));
5437 TmpInst.addOperand(Inst.getOperand(1));
5438 TmpInst.addOperand(Inst.getOperand(2));
5439 TmpInst.addOperand(Inst.getOperand(3));
5440 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005441 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005442 }
5443 break;
5444 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005445 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005446 case ARM::t2SXTB:
5447 case ARM::t2UXTH:
5448 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005449 // If we can use the 16-bit encoding and the user didn't explicitly
5450 // request the 32-bit variant, transform it here.
5451 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5452 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5453 Inst.getOperand(2).getImm() == 0 &&
5454 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5455 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005456 unsigned NewOpc;
5457 switch (Inst.getOpcode()) {
5458 default: llvm_unreachable("Illegal opcode!");
5459 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5460 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5461 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5462 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5463 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005464 // The operands aren't the same for thumb1 (no rotate operand).
5465 MCInst TmpInst;
5466 TmpInst.setOpcode(NewOpc);
5467 TmpInst.addOperand(Inst.getOperand(0));
5468 TmpInst.addOperand(Inst.getOperand(1));
5469 TmpInst.addOperand(Inst.getOperand(3));
5470 TmpInst.addOperand(Inst.getOperand(4));
5471 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005472 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005473 }
5474 break;
5475 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005476 case ARM::t2IT: {
5477 // The mask bits for all but the first condition are represented as
5478 // the low bit of the condition code value implies 't'. We currently
5479 // always have 1 implies 't', so XOR toggle the bits if the low bit
5480 // of the condition code is zero. The encoding also expects the low
5481 // bit of the condition to be encoded as bit 4 of the mask operand,
5482 // so mask that in if needed
5483 MCOperand &MO = Inst.getOperand(1);
5484 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005485 unsigned OrigMask = Mask;
5486 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005487 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005488 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5489 for (unsigned i = 3; i != TZ; --i)
5490 Mask ^= 1 << i;
5491 } else
5492 Mask |= 0x10;
5493 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005494
5495 // Set up the IT block state according to the IT instruction we just
5496 // matched.
5497 assert(!inITBlock() && "nested IT blocks?!");
5498 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5499 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5500 ITState.CurPosition = 0;
5501 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005502 break;
5503 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005504 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005505 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005506}
5507
Jim Grosbach47a0d522011-08-16 20:45:50 +00005508unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5509 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5510 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005511 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005512 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005513 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5514 assert(MCID.hasOptionalDef() &&
5515 "optionally flag setting instruction missing optional def operand");
5516 assert(MCID.NumOperands == Inst.getNumOperands() &&
5517 "operand count mismatch!");
5518 // Find the optional-def operand (cc_out).
5519 unsigned OpNo;
5520 for (OpNo = 0;
5521 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5522 ++OpNo)
5523 ;
5524 // If we're parsing Thumb1, reject it completely.
5525 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5526 return Match_MnemonicFail;
5527 // If we're parsing Thumb2, which form is legal depends on whether we're
5528 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005529 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5530 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005531 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005532 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5533 inITBlock())
5534 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005535 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005536 // Some high-register supporting Thumb1 encodings only allow both registers
5537 // to be from r0-r7 when in Thumb2.
5538 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5539 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5540 isARMLowRegister(Inst.getOperand(2).getReg()))
5541 return Match_RequiresThumb2;
5542 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005543 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005544 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5545 isARMLowRegister(Inst.getOperand(1).getReg()))
5546 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005547 return Match_Success;
5548}
5549
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005550bool ARMAsmParser::
5551MatchAndEmitInstruction(SMLoc IDLoc,
5552 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5553 MCStreamer &Out) {
5554 MCInst Inst;
5555 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005556 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005557 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005558 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005559 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005560 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005561 // Context sensitive operand constraints aren't handled by the matcher,
5562 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005563 if (validateInstruction(Inst, Operands)) {
5564 // Still progress the IT block, otherwise one wrong condition causes
5565 // nasty cascading errors.
5566 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005567 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005568 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005569
Jim Grosbachf8fce712011-08-11 17:35:48 +00005570 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005571 // encoding is selected. Loop on it while changes happen so the
5572 // individual transformations can chain off each other. E.g.,
5573 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5574 while (processInstruction(Inst, Operands))
5575 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005576
Jim Grosbacha1109882011-09-02 23:22:08 +00005577 // Only move forward at the very end so that everything in validate
5578 // and process gets a consistent answer about whether we're in an IT
5579 // block.
5580 forwardITPosition();
5581
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005582 Out.EmitInstruction(Inst);
5583 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005584 case Match_MissingFeature:
5585 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5586 return true;
5587 case Match_InvalidOperand: {
5588 SMLoc ErrorLoc = IDLoc;
5589 if (ErrorInfo != ~0U) {
5590 if (ErrorInfo >= Operands.size())
5591 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005592
Chris Lattnere73d4f82010-10-28 21:41:58 +00005593 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5594 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5595 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005596
Chris Lattnere73d4f82010-10-28 21:41:58 +00005597 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005598 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005599 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005600 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005601 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005602 // The converter function will have already emited a diagnostic.
5603 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005604 case Match_RequiresNotITBlock:
5605 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005606 case Match_RequiresITBlock:
5607 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005608 case Match_RequiresV6:
5609 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5610 case Match_RequiresThumb2:
5611 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005612 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005613
Eric Christopherc223e2b2010-10-29 09:26:59 +00005614 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005615 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005616}
5617
Jim Grosbach1355cf12011-07-26 17:10:22 +00005618/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005619bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5620 StringRef IDVal = DirectiveID.getIdentifier();
5621 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005622 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005623 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005624 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005625 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005626 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005627 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005628 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005629 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005630 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005631 return true;
5632}
5633
Jim Grosbach1355cf12011-07-26 17:10:22 +00005634/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005635/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005636bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5638 for (;;) {
5639 const MCExpr *Value;
5640 if (getParser().ParseExpression(Value))
5641 return true;
5642
Chris Lattneraaec2052010-01-19 19:46:13 +00005643 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005644
5645 if (getLexer().is(AsmToken::EndOfStatement))
5646 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005647
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005648 // FIXME: Improve diagnostic.
5649 if (getLexer().isNot(AsmToken::Comma))
5650 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005651 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005652 }
5653 }
5654
Sean Callananb9a25b72010-01-19 20:27:46 +00005655 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005656 return false;
5657}
5658
Jim Grosbach1355cf12011-07-26 17:10:22 +00005659/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005660/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005661bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005662 if (getLexer().isNot(AsmToken::EndOfStatement))
5663 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005664 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005665
5666 // TODO: set thumb mode
5667 // TODO: tell the MC streamer the mode
5668 // getParser().getStreamer().Emit???();
5669 return false;
5670}
5671
Jim Grosbach1355cf12011-07-26 17:10:22 +00005672/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005673/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005674bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005675 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5676 bool isMachO = MAI.hasSubsectionsViaSymbols();
5677 StringRef Name;
5678
5679 // Darwin asm has function name after .thumb_func direction
5680 // ELF doesn't
5681 if (isMachO) {
5682 const AsmToken &Tok = Parser.getTok();
5683 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5684 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005685 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005686 Parser.Lex(); // Consume the identifier token.
5687 }
5688
Jim Grosbachd475f862011-11-10 20:48:53 +00005689 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005690 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005691 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005692
Rafael Espindola64695402011-05-16 16:17:21 +00005693 // FIXME: assuming function name will be the line following .thumb_func
5694 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005695 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005696 }
5697
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005698 // Mark symbol as a thumb symbol.
5699 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5700 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005701 return false;
5702}
5703
Jim Grosbach1355cf12011-07-26 17:10:22 +00005704/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005705/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005706bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005707 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005708 if (Tok.isNot(AsmToken::Identifier))
5709 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005710 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005711 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005712 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005713 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005714 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005715 else
5716 return Error(L, "unrecognized syntax mode in .syntax directive");
5717
5718 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005719 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005720 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005721
5722 // TODO tell the MC streamer the mode
5723 // getParser().getStreamer().Emit???();
5724 return false;
5725}
5726
Jim Grosbach1355cf12011-07-26 17:10:22 +00005727/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005728/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005729bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005730 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005731 if (Tok.isNot(AsmToken::Integer))
5732 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005733 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005734 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005735 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005736 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005737 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005738 else
5739 return Error(L, "invalid operand to .code directive");
5740
5741 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005742 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005743 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005744
Evan Cheng32869202011-07-08 22:36:29 +00005745 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005746 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005747 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005748 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005749 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005750 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005751 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005752 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005753 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005754
Kevin Enderby515d5092009-10-15 20:48:48 +00005755 return false;
5756}
5757
Sean Callanan90b70972010-04-07 20:29:34 +00005758extern "C" void LLVMInitializeARMAsmLexer();
5759
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005760/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005761extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005762 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5763 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005764 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005765}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005766
Chris Lattner0692ee62010-09-06 19:11:01 +00005767#define GET_REGISTER_MATCHER
5768#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005769#include "ARMGenAsmMatcher.inc"