blob: 153bed4c7b7359c621ec259a528d9da9db847cf3 [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);
Jim Grosbach9a70df92011-12-07 18:04:19 +000095 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveThumbFunc(SMLoc L);
97 bool parseDirectiveCode(SMLoc L);
98 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000099
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000101 bool &CarrySetting, unsigned &ProcessorIMod,
102 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000104 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000105
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 bool isThumb() const {
107 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000112 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000113 bool isThumbTwo() const {
114 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
115 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000116 bool hasV6Ops() const {
117 return STI.getFeatureBits() & ARM::HasV6Ops;
118 }
James Molloyacad68d2011-09-28 14:21:38 +0000119 bool hasV7Ops() const {
120 return STI.getFeatureBits() & ARM::HasV7Ops;
121 }
Evan Cheng32869202011-07-08 22:36:29 +0000122 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000123 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
124 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool isMClass() const {
127 return STI.getFeatureBits() & ARM::FeatureMClass;
128 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000129
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000130 /// @name Auto-generated Match Functions
131 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000132
Chris Lattner0692ee62010-09-06 19:11:01 +0000133#define GET_ASSEMBLER_HEADER
134#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000136 /// }
137
Jim Grosbach89df9962011-08-26 21:43:41 +0000138 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000143 OperandMatchResultTy parseCoprocOptionOperand(
144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000149 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000151 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
152 StringRef Op, int Low, int High);
153 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "lsl", 0, 31);
155 }
156 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
157 return parsePKHImm(O, "asr", 1, 32);
158 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000159 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000160 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000161 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000162 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000163 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000164 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000165 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000166 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000167 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000168
169 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000170 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
172 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000174 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000176 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000180 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000182 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000184 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000186 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000188 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
192 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
194 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000196 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000198 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000200 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000202 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000204 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000208 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
210 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000212
213 bool validateInstruction(MCInst &Inst,
214 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000215 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000216 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000217 bool shouldOmitCCOutOperand(StringRef Mnemonic,
218 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000220public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000221 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000222 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000223 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000224 Match_RequiresV6,
225 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000226 };
227
Evan Chengffc0e732011-07-09 05:47:46 +0000228 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000229 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000230 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000231
Evan Chengebdeeab2011-07-08 01:53:10 +0000232 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000233 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000234
235 // Not in an ITBlock to start with.
236 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 // Implementation of the MCTargetAsmParser interface:
240 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
241 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000242 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool ParseDirective(AsmToken DirectiveID);
244
Jim Grosbach47a0d522011-08-16 20:45:50 +0000245 unsigned checkTargetMatchPredicate(MCInst &Inst);
246
Jim Grosbach1355cf12011-07-26 17:10:22 +0000247 bool MatchAndEmitInstruction(SMLoc IDLoc,
248 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
249 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000250};
Jim Grosbach16c74252010-10-29 14:46:02 +0000251} // end anonymous namespace
252
Chris Lattner3a697562010-10-28 17:20:03 +0000253namespace {
254
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000255/// ARMOperand - Instances of this class represent a parsed ARM machine
256/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000257class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000258 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000259 k_CondCode,
260 k_CCOut,
261 k_ITCondMask,
262 k_CoprocNum,
263 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000264 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000265 k_Immediate,
266 k_FPImmediate,
267 k_MemBarrierOpt,
268 k_Memory,
269 k_PostIndexRegister,
270 k_MSRMask,
271 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000272 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_Register,
274 k_RegisterList,
275 k_DPRRegisterList,
276 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000277 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000278 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000279 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_ShiftedRegister,
281 k_ShiftedImmediate,
282 k_ShifterImmediate,
283 k_RotateImmediate,
284 k_BitfieldDescriptor,
285 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000286 } Kind;
287
Sean Callanan76264762010-04-02 22:27:05 +0000288 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000289 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000290
291 union {
292 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000293 ARMCC::CondCodes Val;
294 } CC;
295
296 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000297 unsigned Val;
298 } Cop;
299
300 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000301 unsigned Val;
302 } CoprocOption;
303
304 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000305 unsigned Mask:4;
306 } ITMask;
307
308 struct {
309 ARM_MB::MemBOpt Val;
310 } MBOpt;
311
312 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000313 ARM_PROC::IFlags Val;
314 } IFlags;
315
316 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000317 unsigned Val;
318 } MMask;
319
320 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000321 const char *Data;
322 unsigned Length;
323 } Tok;
324
325 struct {
326 unsigned RegNum;
327 } Reg;
328
Jim Grosbach862019c2011-10-18 23:02:30 +0000329 // A vector register list is a sequential list of 1 to 4 registers.
330 struct {
331 unsigned RegNum;
332 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000333 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000334 } VectorList;
335
Bill Wendling8155e5b2010-11-06 22:19:43 +0000336 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000337 unsigned Val;
338 } VectorIndex;
339
340 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000341 const MCExpr *Val;
342 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000343
Jim Grosbach9d390362011-10-03 23:38:36 +0000344 struct {
345 unsigned Val; // encoded 8-bit representation
346 } FPImm;
347
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000348 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000349 struct {
350 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000351 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
352 // was specified.
353 const MCConstantExpr *OffsetImm; // Offset immediate value
354 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
355 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000356 unsigned ShiftImm; // shift for OffsetReg.
357 unsigned Alignment; // 0 = no alignment specified
358 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000360 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000361
362 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000363 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000364 bool isAdd;
365 ARM_AM::ShiftOpc ShiftTy;
366 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 } PostIdxReg;
368
369 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000370 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000371 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000372 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftReg;
377 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000378 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000379 struct {
380 ARM_AM::ShiftOpc ShiftTy;
381 unsigned SrcReg;
382 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000383 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000384 struct {
385 unsigned Imm;
386 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000387 struct {
388 unsigned LSB;
389 unsigned Width;
390 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000391 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000392
Bill Wendling146018f2010-11-06 21:42:12 +0000393 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
394public:
Sean Callanan76264762010-04-02 22:27:05 +0000395 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
396 Kind = o.Kind;
397 StartLoc = o.StartLoc;
398 EndLoc = o.EndLoc;
399 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000400 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000401 CC = o.CC;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000404 ITMask = o.ITMask;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000407 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_CCOut:
410 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000411 Reg = o.Reg;
412 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_RegisterList:
414 case k_DPRRegisterList:
415 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000416 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000417 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000418 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000419 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000420 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 VectorList = o.VectorList;
422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_CoprocNum:
424 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000425 Cop = o.Cop;
426 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000427 case k_CoprocOption:
428 CoprocOption = o.CoprocOption;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000431 Imm = o.Imm;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000434 FPImm = o.FPImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000504 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach9d390362011-10-03 23:38:36 +0000508 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000510 return FPImm.Val;
511 }
512
Jim Grosbach460a9052011-10-07 23:56:00 +0000513 unsigned getVectorIndex() const {
514 assert(Kind == k_VectorIndex && "Invalid access!");
515 return VectorIndex.Val;
516 }
517
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000518 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000520 return MBOpt.Val;
521 }
522
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000523 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000525 return IFlags.Val;
526 }
527
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000528 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000530 return MMask.Val;
531 }
532
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000533 bool isCoprocNum() const { return Kind == k_CoprocNum; }
534 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000535 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000536 bool isCondCode() const { return Kind == k_CondCode; }
537 bool isCCOut() const { return Kind == k_CCOut; }
538 bool isITMask() const { return Kind == k_ITCondMask; }
539 bool isITCondCode() const { return Kind == k_CondCode; }
540 bool isImm() const { return Kind == k_Immediate; }
541 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000542 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
549 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000550 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
557 }
558 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
565 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000566 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 256;
573 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000574 bool isImm0_1() const {
575 if (Kind != k_Immediate)
576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 2;
581 }
582 bool isImm0_3() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 4;
589 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000590 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 8;
597 }
598 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 16;
605 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000606 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 32;
613 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000614 bool isImm8() const {
615 if (Kind != k_Immediate)
616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value == 8;
621 }
622 bool isImm16() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value == 16;
629 }
630 bool isImm32() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 32;
637 }
638 bool isImm1_7() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value > 0 && Value < 8;
645 }
646 bool isImm1_15() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value > 0 && Value < 16;
653 }
654 bool isImm1_31() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value < 32;
661 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000662 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000663 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value < 17;
669 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000670 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000671 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value < 33;
677 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000678 bool isImm0_32() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value >= 0 && Value < 33;
685 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000686 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000687 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value >= 0 && Value < 65536;
693 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000694 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000695 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 // If it's not a constant expression, it'll generate a fixup and be
699 // handled later.
700 if (!CE) return true;
701 int64_t Value = CE->getValue();
702 return Value >= 0 && Value < 65536;
703 }
Jim Grosbached838482011-07-26 16:24:27 +0000704 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000705 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000706 return false;
707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
708 if (!CE) return false;
709 int64_t Value = CE->getValue();
710 return Value >= 0 && Value <= 0xffffff;
711 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000712 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000713 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000714 return false;
715 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
716 if (!CE) return false;
717 int64_t Value = CE->getValue();
718 return Value > 0 && Value < 33;
719 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000720 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000721 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000722 return false;
723 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
724 if (!CE) return false;
725 int64_t Value = CE->getValue();
726 return Value >= 0 && Value < 32;
727 }
728 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000729 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000730 return false;
731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 if (!CE) return false;
733 int64_t Value = CE->getValue();
734 return Value > 0 && Value <= 32;
735 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000736 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000737 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000738 return false;
739 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
740 if (!CE) return false;
741 int64_t Value = CE->getValue();
742 return ARM_AM::getSOImmVal(Value) != -1;
743 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000744 bool isARMSOImmNot() const {
745 if (Kind != k_Immediate)
746 return false;
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return ARM_AM::getSOImmVal(~Value) != -1;
751 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000752 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return ARM_AM::getT2SOImmVal(Value) != -1;
759 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000760 bool isT2SOImmNot() const {
761 if (Kind != k_Immediate)
762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return ARM_AM::getT2SOImmVal(~Value) != -1;
767 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000768 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value == 1 || Value == 0;
775 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000776 bool isReg() const { return Kind == k_Register; }
777 bool isRegList() const { return Kind == k_RegisterList; }
778 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
779 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
780 bool isToken() const { return Kind == k_Token; }
781 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
782 bool isMemory() const { return Kind == k_Memory; }
783 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
784 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
785 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
786 bool isRotImm() const { return Kind == k_RotateImmediate; }
787 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
788 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000789 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000790 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000791 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000792 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000793 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000794 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000795 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000796 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
797 (alignOK || Memory.Alignment == 0);
798 }
799 bool isAlignedMemory() const {
800 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000801 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000802 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000803 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000804 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000805 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000806 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000807 if (!Memory.OffsetImm) return true;
808 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000809 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000810 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000811 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000812 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000813 return false;
814 // Immediate offset in range [-4095, 4095].
815 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
816 if (!CE) return false;
817 int64_t Val = CE->getValue();
818 return Val > -4096 && Val < 4096;
819 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000820 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000821 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000822 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000823 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000824 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000825 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000826 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000827 if (!Memory.OffsetImm) return true;
828 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000829 return Val > -256 && Val < 256;
830 }
831 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000832 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000833 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000834 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000835 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
836 // Immediate offset in range [-255, 255].
837 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
838 if (!CE) return false;
839 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000840 // Special case, #-0 is INT32_MIN.
841 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000842 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000843 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000844 // If we have an immediate that's not a constant, treat it as a label
845 // reference needing a fixup. If it is a constant, it's something else
846 // and we reject it.
847 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
848 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000855 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000856 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000857 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000858 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000859 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000861 return false;
862 return true;
863 }
864 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000865 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000866 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
867 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000868 return false;
869 return true;
870 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000871 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000872 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000873 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000874 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000875 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000876 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000877 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
878 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000879 return false;
880 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000882 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000884 return false;
885 return true;
886 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 bool isMemThumbRR() const {
888 // Thumb reg+reg addressing is simple. Just two registers, a base and
889 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000890 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000891 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000892 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000893 return isARMLowRegister(Memory.BaseRegNum) &&
894 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000895 }
896 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000897 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000898 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000899 return false;
900 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (!Memory.OffsetImm) return true;
902 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000903 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
904 }
Jim Grosbach38466302011-08-19 18:55:51 +0000905 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000906 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000907 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000908 return false;
909 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000910 if (!Memory.OffsetImm) return true;
911 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000912 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
913 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000914 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000917 return false;
918 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000919 if (!Memory.OffsetImm) return true;
920 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000921 return Val >= 0 && Val <= 31;
922 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000923 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000924 if (!isMemory() || Memory.OffsetRegNum != 0 ||
925 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000926 return false;
927 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000928 if (!Memory.OffsetImm) return true;
929 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000930 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000931 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000932 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000933 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000934 return false;
935 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000936 if (!Memory.OffsetImm) return true;
937 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000938 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
939 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000940 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000942 return false;
943 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (!Memory.OffsetImm) return true;
945 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000946 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
947 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000948 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000949 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000950 return false;
951 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!Memory.OffsetImm) return true;
953 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000954 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000955 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000956 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000958 return false;
959 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000962 return Val >= 0 && Val < 256;
963 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000964 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000966 return false;
967 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000968 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000970 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000971 }
972 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000974 return false;
975 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (!Memory.OffsetImm) return true;
977 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000978 return (Val >= 0 && Val < 4096);
979 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000980 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000981 // If we have an immediate that's not a constant, treat it as a label
982 // reference needing a fixup. If it is a constant, it's something else
983 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000984 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000985 return true;
986
Jim Grosbach57dcb852011-10-11 17:29:55 +0000987 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000988 return false;
989 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000990 if (!Memory.OffsetImm) return true;
991 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000992 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000993 }
994 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000995 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000996 return false;
997 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
998 if (!CE) return false;
999 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001000 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001001 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001002 bool isPostIdxImm8s4() const {
1003 if (Kind != k_Immediate)
1004 return false;
1005 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1006 if (!CE) return false;
1007 int64_t Val = CE->getValue();
1008 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1009 (Val == INT32_MIN);
1010 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001011
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001012 bool isMSRMask() const { return Kind == k_MSRMask; }
1013 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001014
Jim Grosbach0e387b22011-10-17 22:26:03 +00001015 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001016 bool isVecListOneD() const {
1017 if (Kind != k_VectorList) return false;
1018 return VectorList.Count == 1;
1019 }
1020
Jim Grosbach280dfad2011-10-21 18:54:25 +00001021 bool isVecListTwoD() const {
1022 if (Kind != k_VectorList) return false;
1023 return VectorList.Count == 2;
1024 }
1025
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001026 bool isVecListThreeD() const {
1027 if (Kind != k_VectorList) return false;
1028 return VectorList.Count == 3;
1029 }
1030
Jim Grosbachb6310312011-10-21 20:35:01 +00001031 bool isVecListFourD() const {
1032 if (Kind != k_VectorList) return false;
1033 return VectorList.Count == 4;
1034 }
1035
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001036 bool isVecListTwoQ() const {
1037 if (Kind != k_VectorList) return false;
1038 //FIXME: We haven't taught the parser to handle by-two register lists
1039 // yet, so don't pretend to know one.
1040 return VectorList.Count == 2 && false;
1041 }
1042
Jim Grosbach98b05a52011-11-30 01:09:44 +00001043 bool isVecListOneDAllLanes() const {
1044 if (Kind != k_VectorListAllLanes) return false;
1045 return VectorList.Count == 1;
1046 }
1047
Jim Grosbach13af2222011-11-30 18:21:25 +00001048 bool isVecListTwoDAllLanes() const {
1049 if (Kind != k_VectorListAllLanes) return false;
1050 return VectorList.Count == 2;
1051 }
1052
Jim Grosbach7636bf62011-12-02 00:35:16 +00001053 bool isVecListOneDByteIndexed() const {
1054 if (Kind != k_VectorListIndexed) return false;
1055 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1056 }
1057
Jim Grosbach460a9052011-10-07 23:56:00 +00001058 bool isVectorIndex8() const {
1059 if (Kind != k_VectorIndex) return false;
1060 return VectorIndex.Val < 8;
1061 }
1062 bool isVectorIndex16() const {
1063 if (Kind != k_VectorIndex) return false;
1064 return VectorIndex.Val < 4;
1065 }
1066 bool isVectorIndex32() const {
1067 if (Kind != k_VectorIndex) return false;
1068 return VectorIndex.Val < 2;
1069 }
1070
Jim Grosbach0e387b22011-10-17 22:26:03 +00001071 bool isNEONi8splat() const {
1072 if (Kind != k_Immediate)
1073 return false;
1074 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1075 // Must be a constant.
1076 if (!CE) return false;
1077 int64_t Value = CE->getValue();
1078 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1079 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001080 return Value >= 0 && Value < 256;
1081 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001082
Jim Grosbachea461102011-10-17 23:09:09 +00001083 bool isNEONi16splat() const {
1084 if (Kind != k_Immediate)
1085 return false;
1086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1087 // Must be a constant.
1088 if (!CE) return false;
1089 int64_t Value = CE->getValue();
1090 // i16 value in the range [0,255] or [0x0100, 0xff00]
1091 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1092 }
1093
Jim Grosbach6248a542011-10-18 00:22:00 +00001094 bool isNEONi32splat() const {
1095 if (Kind != k_Immediate)
1096 return false;
1097 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1098 // Must be a constant.
1099 if (!CE) return false;
1100 int64_t Value = CE->getValue();
1101 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1102 return (Value >= 0 && Value < 256) ||
1103 (Value >= 0x0100 && Value <= 0xff00) ||
1104 (Value >= 0x010000 && Value <= 0xff0000) ||
1105 (Value >= 0x01000000 && Value <= 0xff000000);
1106 }
1107
1108 bool isNEONi32vmov() const {
1109 if (Kind != k_Immediate)
1110 return false;
1111 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1112 // Must be a constant.
1113 if (!CE) return false;
1114 int64_t Value = CE->getValue();
1115 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1116 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1117 return (Value >= 0 && Value < 256) ||
1118 (Value >= 0x0100 && Value <= 0xff00) ||
1119 (Value >= 0x010000 && Value <= 0xff0000) ||
1120 (Value >= 0x01000000 && Value <= 0xff000000) ||
1121 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1122 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1123 }
1124
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001125 bool isNEONi64splat() const {
1126 if (Kind != k_Immediate)
1127 return false;
1128 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1129 // Must be a constant.
1130 if (!CE) return false;
1131 uint64_t Value = CE->getValue();
1132 // i64 value with each byte being either 0 or 0xff.
1133 for (unsigned i = 0; i < 8; ++i)
1134 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1135 return true;
1136 }
1137
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001138 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001139 // Add as immediates when possible. Null MCExpr = 0.
1140 if (Expr == 0)
1141 Inst.addOperand(MCOperand::CreateImm(0));
1142 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001143 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1144 else
1145 Inst.addOperand(MCOperand::CreateExpr(Expr));
1146 }
1147
Daniel Dunbar8462b302010-08-11 06:36:53 +00001148 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001149 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001150 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001151 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1152 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001153 }
1154
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001155 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
1157 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1158 }
1159
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001160 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1163 }
1164
1165 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1168 }
1169
Jim Grosbach89df9962011-08-26 21:43:41 +00001170 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1173 }
1174
1175 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1178 }
1179
Jim Grosbachd67641b2010-12-06 18:21:12 +00001180 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 Inst.addOperand(MCOperand::CreateReg(getReg()));
1183 }
1184
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001185 void addRegOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 Inst.addOperand(MCOperand::CreateReg(getReg()));
1188 }
1189
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001190 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001191 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001192 assert(isRegShiftedReg() &&
1193 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001194 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1195 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001196 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001197 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001198 }
1199
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001200 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001201 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001202 assert(isRegShiftedImm() &&
1203 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001204 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001205 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001206 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001207 }
1208
Jim Grosbach580f4a92011-07-25 22:20:28 +00001209 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001210 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001211 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1212 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001213 }
1214
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001215 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001216 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001217 const SmallVectorImpl<unsigned> &RegList = getRegList();
1218 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001219 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1220 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001221 }
1222
Bill Wendling0f630752010-11-17 04:32:08 +00001223 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1224 addRegListOperands(Inst, N);
1225 }
1226
1227 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1228 addRegListOperands(Inst, N);
1229 }
1230
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001231 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1234 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1235 }
1236
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001237 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
1239 // Munge the lsb/width into a bitfield mask.
1240 unsigned lsb = Bitfield.LSB;
1241 unsigned width = Bitfield.Width;
1242 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1243 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1244 (32 - (lsb + width)));
1245 Inst.addOperand(MCOperand::CreateImm(Mask));
1246 }
1247
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001248 void addImmOperands(MCInst &Inst, unsigned N) const {
1249 assert(N == 1 && "Invalid number of operands!");
1250 addExpr(Inst, getImm());
1251 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001252
Jim Grosbach9d390362011-10-03 23:38:36 +00001253 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1254 assert(N == 1 && "Invalid number of operands!");
1255 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1256 }
1257
Jim Grosbacha77295d2011-09-08 22:07:06 +00001258 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1259 assert(N == 1 && "Invalid number of operands!");
1260 // FIXME: We really want to scale the value here, but the LDRD/STRD
1261 // instruction don't encode operands that way yet.
1262 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1263 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1264 }
1265
Jim Grosbach72f39f82011-08-24 21:22:15 +00001266 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 // The immediate is scaled by four in the encoding and is stored
1269 // in the MCInst as such. Lop off the low two bits here.
1270 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1271 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1272 }
1273
1274 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1275 assert(N == 1 && "Invalid number of operands!");
1276 // The immediate is scaled by four in the encoding and is stored
1277 // in the MCInst as such. Lop off the low two bits here.
1278 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1279 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1280 }
1281
Jim Grosbachf4943352011-07-25 23:09:14 +00001282 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
1284 // The constant encodes as the immediate-1, and we store in the instruction
1285 // the bits as encoded, so subtract off one here.
1286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1287 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1288 }
1289
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001290 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 // The constant encodes as the immediate-1, and we store in the instruction
1293 // the bits as encoded, so subtract off one here.
1294 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1295 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1296 }
1297
Jim Grosbach70939ee2011-08-17 21:51:27 +00001298 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
1300 // The constant encodes as the immediate, except for 32, which encodes as
1301 // zero.
1302 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1303 unsigned Imm = CE->getValue();
1304 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1305 }
1306
Jim Grosbachf6c05252011-07-21 17:23:04 +00001307 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
1309 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1310 // the instruction as well.
1311 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1312 int Val = CE->getValue();
1313 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1314 }
1315
Jim Grosbach89a63372011-10-28 22:36:30 +00001316 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
1318 // The operand is actually a t2_so_imm, but we have its bitwise
1319 // negation in the assembly source, so twiddle it here.
1320 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1321 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1322 }
1323
Jim Grosbache70ec842011-10-28 22:50:54 +00001324 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1325 assert(N == 1 && "Invalid number of operands!");
1326 // The operand is actually a so_imm, but we have its bitwise
1327 // negation in the assembly source, so twiddle it here.
1328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1329 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1330 }
1331
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001332 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
1334 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1335 }
1336
Jim Grosbach7ce05792011-08-03 23:50:40 +00001337 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1338 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001339 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001340 }
1341
Jim Grosbach57dcb852011-10-11 17:29:55 +00001342 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1343 assert(N == 2 && "Invalid number of operands!");
1344 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1345 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1346 }
1347
Jim Grosbach7ce05792011-08-03 23:50:40 +00001348 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1349 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001350 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1351 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001352 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1353 // Special case for #-0
1354 if (Val == INT32_MIN) Val = 0;
1355 if (Val < 0) Val = -Val;
1356 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1357 } else {
1358 // For register offset, we encode the shift type and negation flag
1359 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001360 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1361 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001362 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001363 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1364 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001365 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001366 }
1367
Jim Grosbach039c2e12011-08-04 23:01:30 +00001368 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 2 && "Invalid number of operands!");
1370 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1371 assert(CE && "non-constant AM2OffsetImm operand!");
1372 int32_t Val = CE->getValue();
1373 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1374 // Special case for #-0
1375 if (Val == INT32_MIN) Val = 0;
1376 if (Val < 0) Val = -Val;
1377 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1378 Inst.addOperand(MCOperand::CreateReg(0));
1379 Inst.addOperand(MCOperand::CreateImm(Val));
1380 }
1381
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001382 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001384 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1385 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001386 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1387 // Special case for #-0
1388 if (Val == INT32_MIN) Val = 0;
1389 if (Val < 0) Val = -Val;
1390 Val = ARM_AM::getAM3Opc(AddSub, Val);
1391 } else {
1392 // For register offset, we encode the shift type and negation flag
1393 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001394 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001395 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001396 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1397 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001398 Inst.addOperand(MCOperand::CreateImm(Val));
1399 }
1400
1401 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001403 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001404 int32_t Val =
1405 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1406 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1407 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001408 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001409 }
1410
1411 // Constant offset.
1412 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1413 int32_t Val = CE->getValue();
1414 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1415 // Special case for #-0
1416 if (Val == INT32_MIN) Val = 0;
1417 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001418 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001419 Inst.addOperand(MCOperand::CreateReg(0));
1420 Inst.addOperand(MCOperand::CreateImm(Val));
1421 }
1422
Jim Grosbach7ce05792011-08-03 23:50:40 +00001423 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1424 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001425 // If we have an immediate that's not a constant, treat it as a label
1426 // reference needing a fixup. If it is a constant, it's something else
1427 // and we reject it.
1428 if (isImm()) {
1429 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1430 Inst.addOperand(MCOperand::CreateImm(0));
1431 return;
1432 }
1433
Jim Grosbach7ce05792011-08-03 23:50:40 +00001434 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001435 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001436 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1437 // Special case for #-0
1438 if (Val == INT32_MIN) Val = 0;
1439 if (Val < 0) Val = -Val;
1440 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001442 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001443 }
1444
Jim Grosbacha77295d2011-09-08 22:07:06 +00001445 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001447 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1448 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001449 Inst.addOperand(MCOperand::CreateImm(Val));
1450 }
1451
Jim Grosbachb6aed502011-09-09 18:37:27 +00001452 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1453 assert(N == 2 && "Invalid number of operands!");
1454 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001455 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001457 Inst.addOperand(MCOperand::CreateImm(Val));
1458 }
1459
Jim Grosbach7ce05792011-08-03 23:50:40 +00001460 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001462 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1463 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001464 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001465 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001466
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001467 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1468 addMemImm8OffsetOperands(Inst, N);
1469 }
1470
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001471 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001472 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001473 }
1474
1475 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
1477 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001478 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001479 addExpr(Inst, getImm());
1480 Inst.addOperand(MCOperand::CreateImm(0));
1481 return;
1482 }
1483
1484 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001485 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1486 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001487 Inst.addOperand(MCOperand::CreateImm(Val));
1488 }
1489
Jim Grosbach7ce05792011-08-03 23:50:40 +00001490 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001492 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001493 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001494 addExpr(Inst, getImm());
1495 Inst.addOperand(MCOperand::CreateImm(0));
1496 return;
1497 }
1498
1499 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001500 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1501 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001502 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001503 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001504
Jim Grosbach7f739be2011-09-19 22:21:13 +00001505 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1506 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001507 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1508 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001509 }
1510
1511 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001513 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1514 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001515 }
1516
Jim Grosbach7ce05792011-08-03 23:50:40 +00001517 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001519 unsigned Val =
1520 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1521 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001522 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1523 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001524 Inst.addOperand(MCOperand::CreateImm(Val));
1525 }
1526
Jim Grosbachab899c12011-09-07 23:10:15 +00001527 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1528 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001529 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1530 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1531 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001532 }
1533
Jim Grosbach7ce05792011-08-03 23:50:40 +00001534 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001536 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1537 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001538 }
1539
Jim Grosbach60f91a32011-08-19 17:55:24 +00001540 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1541 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001542 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1543 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001544 Inst.addOperand(MCOperand::CreateImm(Val));
1545 }
1546
Jim Grosbach38466302011-08-19 18:55:51 +00001547 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1548 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001549 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1550 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001551 Inst.addOperand(MCOperand::CreateImm(Val));
1552 }
1553
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001554 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001556 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1557 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001558 Inst.addOperand(MCOperand::CreateImm(Val));
1559 }
1560
Jim Grosbachecd85892011-08-19 18:13:48 +00001561 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1562 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001563 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1564 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001565 Inst.addOperand(MCOperand::CreateImm(Val));
1566 }
1567
Jim Grosbach7ce05792011-08-03 23:50:40 +00001568 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1571 assert(CE && "non-constant post-idx-imm8 operand!");
1572 int Imm = CE->getValue();
1573 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001574 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001575 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1576 Inst.addOperand(MCOperand::CreateImm(Imm));
1577 }
1578
Jim Grosbach2bd01182011-10-11 21:55:36 +00001579 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1582 assert(CE && "non-constant post-idx-imm8s4 operand!");
1583 int Imm = CE->getValue();
1584 bool isAdd = Imm >= 0;
1585 if (Imm == INT32_MIN) Imm = 0;
1586 // Immediate is scaled by 4.
1587 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1588 Inst.addOperand(MCOperand::CreateImm(Imm));
1589 }
1590
Jim Grosbach7ce05792011-08-03 23:50:40 +00001591 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1592 assert(N == 2 && "Invalid number of operands!");
1593 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001594 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1595 }
1596
1597 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 2 && "Invalid number of operands!");
1599 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1600 // The sign, shift type, and shift amount are encoded in a single operand
1601 // using the AM2 encoding helpers.
1602 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1603 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1604 PostIdxReg.ShiftTy);
1605 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001606 }
1607
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001608 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1611 }
1612
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001613 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1616 }
1617
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001618 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001619 assert(N == 1 && "Invalid number of operands!");
1620 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1621 }
1622
Jim Grosbach7636bf62011-12-02 00:35:16 +00001623 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1624 assert(N == 2 && "Invalid number of operands!");
1625 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1626 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1627 }
1628
Jim Grosbach460a9052011-10-07 23:56:00 +00001629 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1632 }
1633
1634 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
1636 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1637 }
1638
1639 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1642 }
1643
Jim Grosbach0e387b22011-10-17 22:26:03 +00001644 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1645 assert(N == 1 && "Invalid number of operands!");
1646 // The immediate encodes the type of constant as well as the value.
1647 // Mask in that this is an i8 splat.
1648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1649 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1650 }
1651
Jim Grosbachea461102011-10-17 23:09:09 +00001652 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1653 assert(N == 1 && "Invalid number of operands!");
1654 // The immediate encodes the type of constant as well as the value.
1655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1656 unsigned Value = CE->getValue();
1657 if (Value >= 256)
1658 Value = (Value >> 8) | 0xa00;
1659 else
1660 Value |= 0x800;
1661 Inst.addOperand(MCOperand::CreateImm(Value));
1662 }
1663
Jim Grosbach6248a542011-10-18 00:22:00 +00001664 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1665 assert(N == 1 && "Invalid number of operands!");
1666 // The immediate encodes the type of constant as well as the value.
1667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1668 unsigned Value = CE->getValue();
1669 if (Value >= 256 && Value <= 0xff00)
1670 Value = (Value >> 8) | 0x200;
1671 else if (Value > 0xffff && Value <= 0xff0000)
1672 Value = (Value >> 16) | 0x400;
1673 else if (Value > 0xffffff)
1674 Value = (Value >> 24) | 0x600;
1675 Inst.addOperand(MCOperand::CreateImm(Value));
1676 }
1677
1678 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1679 assert(N == 1 && "Invalid number of operands!");
1680 // The immediate encodes the type of constant as well as the value.
1681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1682 unsigned Value = CE->getValue();
1683 if (Value >= 256 && Value <= 0xffff)
1684 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1685 else if (Value > 0xffff && Value <= 0xffffff)
1686 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1687 else if (Value > 0xffffff)
1688 Value = (Value >> 24) | 0x600;
1689 Inst.addOperand(MCOperand::CreateImm(Value));
1690 }
1691
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001692 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 1 && "Invalid number of operands!");
1694 // The immediate encodes the type of constant as well as the value.
1695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1696 uint64_t Value = CE->getValue();
1697 unsigned Imm = 0;
1698 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1699 Imm |= (Value & 1) << i;
1700 }
1701 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1702 }
1703
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001704 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001705
Jim Grosbach89df9962011-08-26 21:43:41 +00001706 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001707 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001708 Op->ITMask.Mask = Mask;
1709 Op->StartLoc = S;
1710 Op->EndLoc = S;
1711 return Op;
1712 }
1713
Chris Lattner3a697562010-10-28 17:20:03 +00001714 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001715 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001716 Op->CC.Val = CC;
1717 Op->StartLoc = S;
1718 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001719 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001720 }
1721
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001722 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001723 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001724 Op->Cop.Val = CopVal;
1725 Op->StartLoc = S;
1726 Op->EndLoc = S;
1727 return Op;
1728 }
1729
1730 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001731 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001732 Op->Cop.Val = CopVal;
1733 Op->StartLoc = S;
1734 Op->EndLoc = S;
1735 return Op;
1736 }
1737
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001738 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1739 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1740 Op->Cop.Val = Val;
1741 Op->StartLoc = S;
1742 Op->EndLoc = E;
1743 return Op;
1744 }
1745
Jim Grosbachd67641b2010-12-06 18:21:12 +00001746 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001747 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001748 Op->Reg.RegNum = RegNum;
1749 Op->StartLoc = S;
1750 Op->EndLoc = S;
1751 return Op;
1752 }
1753
Chris Lattner3a697562010-10-28 17:20:03 +00001754 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001756 Op->Tok.Data = Str.data();
1757 Op->Tok.Length = Str.size();
1758 Op->StartLoc = S;
1759 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001760 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001761 }
1762
Bill Wendling50d0f582010-11-18 23:43:05 +00001763 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001765 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001766 Op->StartLoc = S;
1767 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001768 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001769 }
1770
Jim Grosbache8606dc2011-07-13 17:50:29 +00001771 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1772 unsigned SrcReg,
1773 unsigned ShiftReg,
1774 unsigned ShiftImm,
1775 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001776 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001777 Op->RegShiftedReg.ShiftTy = ShTy;
1778 Op->RegShiftedReg.SrcReg = SrcReg;
1779 Op->RegShiftedReg.ShiftReg = ShiftReg;
1780 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001781 Op->StartLoc = S;
1782 Op->EndLoc = E;
1783 return Op;
1784 }
1785
Owen Anderson92a20222011-07-21 18:54:16 +00001786 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1787 unsigned SrcReg,
1788 unsigned ShiftImm,
1789 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001790 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001791 Op->RegShiftedImm.ShiftTy = ShTy;
1792 Op->RegShiftedImm.SrcReg = SrcReg;
1793 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001794 Op->StartLoc = S;
1795 Op->EndLoc = E;
1796 return Op;
1797 }
1798
Jim Grosbach580f4a92011-07-25 22:20:28 +00001799 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001800 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001801 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001802 Op->ShifterImm.isASR = isASR;
1803 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001804 Op->StartLoc = S;
1805 Op->EndLoc = E;
1806 return Op;
1807 }
1808
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001809 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001811 Op->RotImm.Imm = Imm;
1812 Op->StartLoc = S;
1813 Op->EndLoc = E;
1814 return Op;
1815 }
1816
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001817 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1818 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001819 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001820 Op->Bitfield.LSB = LSB;
1821 Op->Bitfield.Width = Width;
1822 Op->StartLoc = S;
1823 Op->EndLoc = E;
1824 return Op;
1825 }
1826
Bill Wendling7729e062010-11-09 22:44:22 +00001827 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001828 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001829 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001830 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001831
Jim Grosbachd300b942011-09-13 22:56:44 +00001832 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001833 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001834 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001835 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001836 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001837
1838 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001839 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001840 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001841 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001842 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001843 Op->StartLoc = StartLoc;
1844 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001845 return Op;
1846 }
1847
Jim Grosbach862019c2011-10-18 23:02:30 +00001848 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1849 SMLoc S, SMLoc E) {
1850 ARMOperand *Op = new ARMOperand(k_VectorList);
1851 Op->VectorList.RegNum = RegNum;
1852 Op->VectorList.Count = Count;
1853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
Jim Grosbach98b05a52011-11-30 01:09:44 +00001858 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1859 SMLoc S, SMLoc E) {
1860 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1861 Op->VectorList.RegNum = RegNum;
1862 Op->VectorList.Count = Count;
1863 Op->StartLoc = S;
1864 Op->EndLoc = E;
1865 return Op;
1866 }
1867
Jim Grosbach7636bf62011-12-02 00:35:16 +00001868 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1869 unsigned Index, SMLoc S, SMLoc E) {
1870 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1871 Op->VectorList.RegNum = RegNum;
1872 Op->VectorList.Count = Count;
1873 Op->VectorList.LaneIndex = Index;
1874 Op->StartLoc = S;
1875 Op->EndLoc = E;
1876 return Op;
1877 }
1878
Jim Grosbach460a9052011-10-07 23:56:00 +00001879 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1880 MCContext &Ctx) {
1881 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1882 Op->VectorIndex.Val = Idx;
1883 Op->StartLoc = S;
1884 Op->EndLoc = E;
1885 return Op;
1886 }
1887
Chris Lattner3a697562010-10-28 17:20:03 +00001888 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001889 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001890 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001891 Op->StartLoc = S;
1892 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001893 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001894 }
1895
Jim Grosbach9d390362011-10-03 23:38:36 +00001896 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001898 Op->FPImm.Val = Val;
1899 Op->StartLoc = S;
1900 Op->EndLoc = S;
1901 return Op;
1902 }
1903
Jim Grosbach7ce05792011-08-03 23:50:40 +00001904 static ARMOperand *CreateMem(unsigned BaseRegNum,
1905 const MCConstantExpr *OffsetImm,
1906 unsigned OffsetRegNum,
1907 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001908 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001909 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001910 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001911 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001913 Op->Memory.BaseRegNum = BaseRegNum;
1914 Op->Memory.OffsetImm = OffsetImm;
1915 Op->Memory.OffsetRegNum = OffsetRegNum;
1916 Op->Memory.ShiftType = ShiftType;
1917 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001918 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001919 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001920 Op->StartLoc = S;
1921 Op->EndLoc = E;
1922 return Op;
1923 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001924
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001925 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1926 ARM_AM::ShiftOpc ShiftTy,
1927 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001928 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001929 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001930 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001931 Op->PostIdxReg.isAdd = isAdd;
1932 Op->PostIdxReg.ShiftTy = ShiftTy;
1933 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001934 Op->StartLoc = S;
1935 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001936 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001937 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001938
1939 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001941 Op->MBOpt.Val = Opt;
1942 Op->StartLoc = S;
1943 Op->EndLoc = S;
1944 return Op;
1945 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001946
1947 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001948 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001949 Op->IFlags.Val = IFlags;
1950 Op->StartLoc = S;
1951 Op->EndLoc = S;
1952 return Op;
1953 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001954
1955 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001956 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001957 Op->MMask.Val = MMask;
1958 Op->StartLoc = S;
1959 Op->EndLoc = S;
1960 return Op;
1961 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001962};
1963
1964} // end anonymous namespace.
1965
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001966void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001967 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001968 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001969 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1970 << ") >";
1971 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001972 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001973 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001974 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001975 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001976 OS << "<ccout " << getReg() << ">";
1977 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001978 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001979 static const char *MaskStr[] = {
1980 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1981 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1982 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001983 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1984 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1985 break;
1986 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001987 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001988 OS << "<coprocessor number: " << getCoproc() << ">";
1989 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001990 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001991 OS << "<coprocessor register: " << getCoproc() << ">";
1992 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001993 case k_CoprocOption:
1994 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1995 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001997 OS << "<mask: " << getMSRMask() << ">";
1998 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001999 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002000 getImm()->print(OS);
2001 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002002 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002003 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2004 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002005 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002006 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002007 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002008 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002009 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002010 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002011 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2012 << PostIdxReg.RegNum;
2013 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2014 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2015 << PostIdxReg.ShiftImm;
2016 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002017 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002018 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002019 OS << "<ARM_PROC::";
2020 unsigned IFlags = getProcIFlags();
2021 for (int i=2; i >= 0; --i)
2022 if (IFlags & (1 << i))
2023 OS << ARM_PROC::IFlagsToString(1 << i);
2024 OS << ">";
2025 break;
2026 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002027 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002028 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002029 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002030 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002031 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2032 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002033 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002034 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002035 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002036 << RegShiftedReg.SrcReg << " "
2037 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2038 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002039 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002040 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002041 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002042 << RegShiftedImm.SrcReg << " "
2043 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2044 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002045 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002046 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002047 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2048 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002049 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002050 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2051 << ", width: " << Bitfield.Width << ">";
2052 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002053 case k_RegisterList:
2054 case k_DPRRegisterList:
2055 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002056 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002057
Bill Wendling5fa22a12010-11-09 23:28:44 +00002058 const SmallVectorImpl<unsigned> &RegList = getRegList();
2059 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002060 I = RegList.begin(), E = RegList.end(); I != E; ) {
2061 OS << *I;
2062 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002063 }
2064
2065 OS << ">";
2066 break;
2067 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002068 case k_VectorList:
2069 OS << "<vector_list " << VectorList.Count << " * "
2070 << VectorList.RegNum << ">";
2071 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002072 case k_VectorListAllLanes:
2073 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2074 << VectorList.RegNum << ">";
2075 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002076 case k_VectorListIndexed:
2077 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2078 << VectorList.Count << " * " << VectorList.RegNum << ">";
2079 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002080 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002081 OS << "'" << getToken() << "'";
2082 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002083 case k_VectorIndex:
2084 OS << "<vectorindex " << getVectorIndex() << ">";
2085 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002086 }
2087}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002088
2089/// @name Auto-generated Match Functions
2090/// {
2091
2092static unsigned MatchRegisterName(StringRef Name);
2093
2094/// }
2095
Bob Wilson69df7232011-02-03 21:46:10 +00002096bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2097 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002098 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002099
2100 return (RegNo == (unsigned)-1);
2101}
2102
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002103/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002104/// and if it is a register name the token is eaten and the register number is
2105/// returned. Otherwise return -1.
2106///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002107int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002108 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002109 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002110
Chris Lattnere5658fa2010-10-30 04:09:10 +00002111 // FIXME: Validate register for the current architecture; we have to do
2112 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002113 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002114 unsigned RegNum = MatchRegisterName(lowerCase);
2115 if (!RegNum) {
2116 RegNum = StringSwitch<unsigned>(lowerCase)
2117 .Case("r13", ARM::SP)
2118 .Case("r14", ARM::LR)
2119 .Case("r15", ARM::PC)
2120 .Case("ip", ARM::R12)
2121 .Default(0);
2122 }
2123 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002124
Chris Lattnere5658fa2010-10-30 04:09:10 +00002125 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002126
Chris Lattnere5658fa2010-10-30 04:09:10 +00002127 return RegNum;
2128}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002129
Jim Grosbach19906722011-07-13 18:49:30 +00002130// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2131// If a recoverable error occurs, return 1. If an irrecoverable error
2132// occurs, return -1. An irrecoverable error is one where tokens have been
2133// consumed in the process of trying to parse the shifter (i.e., when it is
2134// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002135int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002136 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2137 SMLoc S = Parser.getTok().getLoc();
2138 const AsmToken &Tok = Parser.getTok();
2139 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2140
Benjamin Kramer59085362011-11-06 20:37:06 +00002141 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002142 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002143 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002144 .Case("lsl", ARM_AM::lsl)
2145 .Case("lsr", ARM_AM::lsr)
2146 .Case("asr", ARM_AM::asr)
2147 .Case("ror", ARM_AM::ror)
2148 .Case("rrx", ARM_AM::rrx)
2149 .Default(ARM_AM::no_shift);
2150
2151 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002152 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002153
Jim Grosbache8606dc2011-07-13 17:50:29 +00002154 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002155
Jim Grosbache8606dc2011-07-13 17:50:29 +00002156 // The source register for the shift has already been added to the
2157 // operand list, so we need to pop it off and combine it into the shifted
2158 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002159 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002160 if (!PrevOp->isReg())
2161 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2162 int SrcReg = PrevOp->getReg();
2163 int64_t Imm = 0;
2164 int ShiftReg = 0;
2165 if (ShiftTy == ARM_AM::rrx) {
2166 // RRX Doesn't have an explicit shift amount. The encoder expects
2167 // the shift register to be the same as the source register. Seems odd,
2168 // but OK.
2169 ShiftReg = SrcReg;
2170 } else {
2171 // Figure out if this is shifted by a constant or a register (for non-RRX).
2172 if (Parser.getTok().is(AsmToken::Hash)) {
2173 Parser.Lex(); // Eat hash.
2174 SMLoc ImmLoc = Parser.getTok().getLoc();
2175 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002176 if (getParser().ParseExpression(ShiftExpr)) {
2177 Error(ImmLoc, "invalid immediate shift value");
2178 return -1;
2179 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002180 // The expression must be evaluatable as an immediate.
2181 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002182 if (!CE) {
2183 Error(ImmLoc, "invalid immediate shift value");
2184 return -1;
2185 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002186 // Range check the immediate.
2187 // lsl, ror: 0 <= imm <= 31
2188 // lsr, asr: 0 <= imm <= 32
2189 Imm = CE->getValue();
2190 if (Imm < 0 ||
2191 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2192 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002193 Error(ImmLoc, "immediate shift value out of range");
2194 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002195 }
2196 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002197 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002198 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002199 if (ShiftReg == -1) {
2200 Error (L, "expected immediate or register in shift operand");
2201 return -1;
2202 }
2203 } else {
2204 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002205 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002206 return -1;
2207 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002208 }
2209
Owen Anderson92a20222011-07-21 18:54:16 +00002210 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2211 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002212 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002213 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002214 else
2215 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2216 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002217
Jim Grosbach19906722011-07-13 18:49:30 +00002218 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002219}
2220
2221
Bill Wendling50d0f582010-11-18 23:43:05 +00002222/// Try to parse a register name. The token must be an Identifier when called.
2223/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2224/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002225///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002226/// TODO this is likely to change to allow different register types and or to
2227/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002228bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002229tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002230 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002231 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002232 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002233 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002234
Bill Wendling50d0f582010-11-18 23:43:05 +00002235 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002236
Chris Lattnere5658fa2010-10-30 04:09:10 +00002237 const AsmToken &ExclaimTok = Parser.getTok();
2238 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002239 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2240 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002241 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002242 return false;
2243 }
2244
2245 // Also check for an index operand. This is only legal for vector registers,
2246 // but that'll get caught OK in operand matching, so we don't need to
2247 // explicitly filter everything else out here.
2248 if (Parser.getTok().is(AsmToken::LBrac)) {
2249 SMLoc SIdx = Parser.getTok().getLoc();
2250 Parser.Lex(); // Eat left bracket token.
2251
2252 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002253 if (getParser().ParseExpression(ImmVal))
2254 return MatchOperand_ParseFail;
2255 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2256 if (!MCE) {
2257 TokError("immediate value expected for vector index");
2258 return MatchOperand_ParseFail;
2259 }
2260
2261 SMLoc E = Parser.getTok().getLoc();
2262 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2263 Error(E, "']' expected");
2264 return MatchOperand_ParseFail;
2265 }
2266
2267 Parser.Lex(); // Eat right bracket token.
2268
2269 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2270 SIdx, E,
2271 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002272 }
2273
Bill Wendling50d0f582010-11-18 23:43:05 +00002274 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002275}
2276
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002277/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2278/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2279/// "c5", ...
2280static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002281 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2282 // but efficient.
2283 switch (Name.size()) {
2284 default: break;
2285 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002286 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002287 return -1;
2288 switch (Name[1]) {
2289 default: return -1;
2290 case '0': return 0;
2291 case '1': return 1;
2292 case '2': return 2;
2293 case '3': return 3;
2294 case '4': return 4;
2295 case '5': return 5;
2296 case '6': return 6;
2297 case '7': return 7;
2298 case '8': return 8;
2299 case '9': return 9;
2300 }
2301 break;
2302 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002303 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002304 return -1;
2305 switch (Name[2]) {
2306 default: return -1;
2307 case '0': return 10;
2308 case '1': return 11;
2309 case '2': return 12;
2310 case '3': return 13;
2311 case '4': return 14;
2312 case '5': return 15;
2313 }
2314 break;
2315 }
2316
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002317 return -1;
2318}
2319
Jim Grosbach89df9962011-08-26 21:43:41 +00002320/// parseITCondCode - Try to parse a condition code for an IT instruction.
2321ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2322parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2323 SMLoc S = Parser.getTok().getLoc();
2324 const AsmToken &Tok = Parser.getTok();
2325 if (!Tok.is(AsmToken::Identifier))
2326 return MatchOperand_NoMatch;
2327 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2328 .Case("eq", ARMCC::EQ)
2329 .Case("ne", ARMCC::NE)
2330 .Case("hs", ARMCC::HS)
2331 .Case("cs", ARMCC::HS)
2332 .Case("lo", ARMCC::LO)
2333 .Case("cc", ARMCC::LO)
2334 .Case("mi", ARMCC::MI)
2335 .Case("pl", ARMCC::PL)
2336 .Case("vs", ARMCC::VS)
2337 .Case("vc", ARMCC::VC)
2338 .Case("hi", ARMCC::HI)
2339 .Case("ls", ARMCC::LS)
2340 .Case("ge", ARMCC::GE)
2341 .Case("lt", ARMCC::LT)
2342 .Case("gt", ARMCC::GT)
2343 .Case("le", ARMCC::LE)
2344 .Case("al", ARMCC::AL)
2345 .Default(~0U);
2346 if (CC == ~0U)
2347 return MatchOperand_NoMatch;
2348 Parser.Lex(); // Eat the token.
2349
2350 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2351
2352 return MatchOperand_Success;
2353}
2354
Jim Grosbach43904292011-07-25 20:14:50 +00002355/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002356/// token must be an Identifier when called, and if it is a coprocessor
2357/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002358ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002359parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002360 SMLoc S = Parser.getTok().getLoc();
2361 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002362 if (Tok.isNot(AsmToken::Identifier))
2363 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002364
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002365 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002366 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002367 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002368
2369 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002370 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002371 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002372}
2373
Jim Grosbach43904292011-07-25 20:14:50 +00002374/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002375/// token must be an Identifier when called, and if it is a coprocessor
2376/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002377ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002378parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002379 SMLoc S = Parser.getTok().getLoc();
2380 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002381 if (Tok.isNot(AsmToken::Identifier))
2382 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002383
2384 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2385 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002386 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002387
2388 Parser.Lex(); // Eat identifier token.
2389 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002390 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002391}
2392
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002393/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2394/// coproc_option : '{' imm0_255 '}'
2395ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2396parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2397 SMLoc S = Parser.getTok().getLoc();
2398
2399 // If this isn't a '{', this isn't a coprocessor immediate operand.
2400 if (Parser.getTok().isNot(AsmToken::LCurly))
2401 return MatchOperand_NoMatch;
2402 Parser.Lex(); // Eat the '{'
2403
2404 const MCExpr *Expr;
2405 SMLoc Loc = Parser.getTok().getLoc();
2406 if (getParser().ParseExpression(Expr)) {
2407 Error(Loc, "illegal expression");
2408 return MatchOperand_ParseFail;
2409 }
2410 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2411 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2412 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2413 return MatchOperand_ParseFail;
2414 }
2415 int Val = CE->getValue();
2416
2417 // Check for and consume the closing '}'
2418 if (Parser.getTok().isNot(AsmToken::RCurly))
2419 return MatchOperand_ParseFail;
2420 SMLoc E = Parser.getTok().getLoc();
2421 Parser.Lex(); // Eat the '}'
2422
2423 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2424 return MatchOperand_Success;
2425}
2426
Jim Grosbachd0588e22011-09-14 18:08:35 +00002427// For register list parsing, we need to map from raw GPR register numbering
2428// to the enumeration values. The enumeration values aren't sorted by
2429// register number due to our using "sp", "lr" and "pc" as canonical names.
2430static unsigned getNextRegister(unsigned Reg) {
2431 // If this is a GPR, we need to do it manually, otherwise we can rely
2432 // on the sort ordering of the enumeration since the other reg-classes
2433 // are sane.
2434 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2435 return Reg + 1;
2436 switch(Reg) {
2437 default: assert(0 && "Invalid GPR number!");
2438 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2439 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2440 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2441 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2442 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2443 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2444 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2445 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2446 }
2447}
2448
Jim Grosbachce485e72011-11-11 21:27:40 +00002449// Return the low-subreg of a given Q register.
2450static unsigned getDRegFromQReg(unsigned QReg) {
2451 switch (QReg) {
2452 default: llvm_unreachable("expected a Q register!");
2453 case ARM::Q0: return ARM::D0;
2454 case ARM::Q1: return ARM::D2;
2455 case ARM::Q2: return ARM::D4;
2456 case ARM::Q3: return ARM::D6;
2457 case ARM::Q4: return ARM::D8;
2458 case ARM::Q5: return ARM::D10;
2459 case ARM::Q6: return ARM::D12;
2460 case ARM::Q7: return ARM::D14;
2461 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002462 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002463 case ARM::Q10: return ARM::D20;
2464 case ARM::Q11: return ARM::D22;
2465 case ARM::Q12: return ARM::D24;
2466 case ARM::Q13: return ARM::D26;
2467 case ARM::Q14: return ARM::D28;
2468 case ARM::Q15: return ARM::D30;
2469 }
2470}
2471
Jim Grosbachd0588e22011-09-14 18:08:35 +00002472/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002473bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002474parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002475 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002476 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002477 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002478 Parser.Lex(); // Eat '{' token.
2479 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002480
Jim Grosbachd0588e22011-09-14 18:08:35 +00002481 // Check the first register in the list to see what register class
2482 // this is a list of.
2483 int Reg = tryParseRegister();
2484 if (Reg == -1)
2485 return Error(RegLoc, "register expected");
2486
Jim Grosbachce485e72011-11-11 21:27:40 +00002487 // The reglist instructions have at most 16 registers, so reserve
2488 // space for that many.
2489 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2490
2491 // Allow Q regs and just interpret them as the two D sub-registers.
2492 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2493 Reg = getDRegFromQReg(Reg);
2494 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2495 ++Reg;
2496 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002497 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002498 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2499 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2500 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2501 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2502 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2503 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2504 else
2505 return Error(RegLoc, "invalid register in register list");
2506
Jim Grosbachce485e72011-11-11 21:27:40 +00002507 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002508 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002509
Jim Grosbachd0588e22011-09-14 18:08:35 +00002510 // This starts immediately after the first register token in the list,
2511 // so we can see either a comma or a minus (range separator) as a legal
2512 // next token.
2513 while (Parser.getTok().is(AsmToken::Comma) ||
2514 Parser.getTok().is(AsmToken::Minus)) {
2515 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002516 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002517 SMLoc EndLoc = Parser.getTok().getLoc();
2518 int EndReg = tryParseRegister();
2519 if (EndReg == -1)
2520 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002521 // Allow Q regs and just interpret them as the two D sub-registers.
2522 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2523 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002524 // If the register is the same as the start reg, there's nothing
2525 // more to do.
2526 if (Reg == EndReg)
2527 continue;
2528 // The register must be in the same register class as the first.
2529 if (!RC->contains(EndReg))
2530 return Error(EndLoc, "invalid register in register list");
2531 // Ranges must go from low to high.
2532 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2533 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002534
Jim Grosbachd0588e22011-09-14 18:08:35 +00002535 // Add all the registers in the range to the register list.
2536 while (Reg != EndReg) {
2537 Reg = getNextRegister(Reg);
2538 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2539 }
2540 continue;
2541 }
2542 Parser.Lex(); // Eat the comma.
2543 RegLoc = Parser.getTok().getLoc();
2544 int OldReg = Reg;
2545 Reg = tryParseRegister();
2546 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002547 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002548 // Allow Q regs and just interpret them as the two D sub-registers.
2549 bool isQReg = false;
2550 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2551 Reg = getDRegFromQReg(Reg);
2552 isQReg = true;
2553 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002554 // The register must be in the same register class as the first.
2555 if (!RC->contains(Reg))
2556 return Error(RegLoc, "invalid register in register list");
2557 // List must be monotonically increasing.
2558 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2559 return Error(RegLoc, "register list not in ascending order");
2560 // VFP register lists must also be contiguous.
2561 // It's OK to use the enumeration values directly here rather, as the
2562 // VFP register classes have the enum sorted properly.
2563 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2564 Reg != OldReg + 1)
2565 return Error(RegLoc, "non-contiguous register range");
2566 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002567 if (isQReg)
2568 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002569 }
2570
Jim Grosbachd0588e22011-09-14 18:08:35 +00002571 SMLoc E = Parser.getTok().getLoc();
2572 if (Parser.getTok().isNot(AsmToken::RCurly))
2573 return Error(E, "'}' expected");
2574 Parser.Lex(); // Eat '}' token.
2575
Bill Wendling50d0f582010-11-18 23:43:05 +00002576 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2577 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002578}
2579
Jim Grosbach98b05a52011-11-30 01:09:44 +00002580// Helper function to parse the lane index for vector lists.
2581ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002582parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2583 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002584 if (Parser.getTok().is(AsmToken::LBrac)) {
2585 Parser.Lex(); // Eat the '['.
2586 if (Parser.getTok().is(AsmToken::RBrac)) {
2587 // "Dn[]" is the 'all lanes' syntax.
2588 LaneKind = AllLanes;
2589 Parser.Lex(); // Eat the ']'.
2590 return MatchOperand_Success;
2591 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002592 if (Parser.getTok().is(AsmToken::Integer)) {
2593 int64_t Val = Parser.getTok().getIntVal();
2594 // Make this range check context sensitive for .8, .16, .32.
2595 if (Val < 0 && Val > 7)
2596 Error(Parser.getTok().getLoc(), "lane index out of range");
2597 Index = Val;
2598 LaneKind = IndexedLane;
2599 Parser.Lex(); // Eat the token;
2600 if (Parser.getTok().isNot(AsmToken::RBrac))
2601 Error(Parser.getTok().getLoc(), "']' expected");
2602 Parser.Lex(); // Eat the ']'.
2603 return MatchOperand_Success;
2604 }
2605 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002606 return MatchOperand_ParseFail;
2607 }
2608 LaneKind = NoLanes;
2609 return MatchOperand_Success;
2610}
2611
Jim Grosbach862019c2011-10-18 23:02:30 +00002612// parse a vector register list
2613ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2614parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002615 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002616 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002617 SMLoc S = Parser.getTok().getLoc();
2618 // As an extension (to match gas), support a plain D register or Q register
2619 // (without encosing curly braces) as a single or double entry list,
2620 // respectively.
2621 if (Parser.getTok().is(AsmToken::Identifier)) {
2622 int Reg = tryParseRegister();
2623 if (Reg == -1)
2624 return MatchOperand_NoMatch;
2625 SMLoc E = Parser.getTok().getLoc();
2626 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002627 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002628 if (Res != MatchOperand_Success)
2629 return Res;
2630 switch (LaneKind) {
2631 default:
2632 assert(0 && "unexpected lane kind!");
2633 case NoLanes:
2634 E = Parser.getTok().getLoc();
2635 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2636 break;
2637 case AllLanes:
2638 E = Parser.getTok().getLoc();
2639 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2640 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002641 case IndexedLane:
2642 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2643 LaneIndex, S,E));
2644 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002645 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002646 return MatchOperand_Success;
2647 }
2648 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2649 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002650 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002651 if (Res != MatchOperand_Success)
2652 return Res;
2653 switch (LaneKind) {
2654 default:
2655 assert(0 && "unexpected lane kind!");
2656 case NoLanes:
2657 E = Parser.getTok().getLoc();
2658 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2659 break;
2660 case AllLanes:
2661 E = Parser.getTok().getLoc();
2662 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2663 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002664 case IndexedLane:
2665 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2666 LaneIndex, S,E));
2667 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002668 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002669 return MatchOperand_Success;
2670 }
2671 Error(S, "vector register expected");
2672 return MatchOperand_ParseFail;
2673 }
2674
2675 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002676 return MatchOperand_NoMatch;
2677
Jim Grosbach862019c2011-10-18 23:02:30 +00002678 Parser.Lex(); // Eat '{' token.
2679 SMLoc RegLoc = Parser.getTok().getLoc();
2680
2681 int Reg = tryParseRegister();
2682 if (Reg == -1) {
2683 Error(RegLoc, "register expected");
2684 return MatchOperand_ParseFail;
2685 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002686 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002687 unsigned FirstReg = Reg;
2688 // The list is of D registers, but we also allow Q regs and just interpret
2689 // them as the two D sub-registers.
2690 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2691 FirstReg = Reg = getDRegFromQReg(Reg);
2692 ++Reg;
2693 ++Count;
2694 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002695 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002696 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002697
Jim Grosbache43862b2011-11-15 23:19:15 +00002698 while (Parser.getTok().is(AsmToken::Comma) ||
2699 Parser.getTok().is(AsmToken::Minus)) {
2700 if (Parser.getTok().is(AsmToken::Minus)) {
2701 Parser.Lex(); // Eat the minus.
2702 SMLoc EndLoc = Parser.getTok().getLoc();
2703 int EndReg = tryParseRegister();
2704 if (EndReg == -1) {
2705 Error(EndLoc, "register expected");
2706 return MatchOperand_ParseFail;
2707 }
2708 // Allow Q regs and just interpret them as the two D sub-registers.
2709 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2710 EndReg = getDRegFromQReg(EndReg) + 1;
2711 // If the register is the same as the start reg, there's nothing
2712 // more to do.
2713 if (Reg == EndReg)
2714 continue;
2715 // The register must be in the same register class as the first.
2716 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2717 Error(EndLoc, "invalid register in register list");
2718 return MatchOperand_ParseFail;
2719 }
2720 // Ranges must go from low to high.
2721 if (Reg > EndReg) {
2722 Error(EndLoc, "bad range in register list");
2723 return MatchOperand_ParseFail;
2724 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002725 // Parse the lane specifier if present.
2726 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002727 unsigned NextLaneIndex;
2728 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002729 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002730 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002731 Error(EndLoc, "mismatched lane index in register list");
2732 return MatchOperand_ParseFail;
2733 }
2734 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002735
2736 // Add all the registers in the range to the register list.
2737 Count += EndReg - Reg;
2738 Reg = EndReg;
2739 continue;
2740 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002741 Parser.Lex(); // Eat the comma.
2742 RegLoc = Parser.getTok().getLoc();
2743 int OldReg = Reg;
2744 Reg = tryParseRegister();
2745 if (Reg == -1) {
2746 Error(RegLoc, "register expected");
2747 return MatchOperand_ParseFail;
2748 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002749 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002750 // It's OK to use the enumeration values directly here rather, as the
2751 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002752 //
2753 // The list is of D registers, but we also allow Q regs and just interpret
2754 // them as the two D sub-registers.
2755 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2756 Reg = getDRegFromQReg(Reg);
2757 if (Reg != OldReg + 1) {
2758 Error(RegLoc, "non-contiguous register range");
2759 return MatchOperand_ParseFail;
2760 }
2761 ++Reg;
2762 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002763 // Parse the lane specifier if present.
2764 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002765 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002766 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002767 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002768 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002769 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002770 Error(EndLoc, "mismatched lane index in register list");
2771 return MatchOperand_ParseFail;
2772 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002773 continue;
2774 }
2775 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002776 if (Reg != OldReg + 1) {
2777 Error(RegLoc, "non-contiguous register range");
2778 return MatchOperand_ParseFail;
2779 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002780 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002781 // Parse the lane specifier if present.
2782 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002783 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002784 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002785 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002786 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002787 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002788 Error(EndLoc, "mismatched lane index in register list");
2789 return MatchOperand_ParseFail;
2790 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002791 }
2792
2793 SMLoc E = Parser.getTok().getLoc();
2794 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2795 Error(E, "'}' expected");
2796 return MatchOperand_ParseFail;
2797 }
2798 Parser.Lex(); // Eat '}' token.
2799
Jim Grosbach98b05a52011-11-30 01:09:44 +00002800 switch (LaneKind) {
2801 default:
2802 assert(0 && "unexpected lane kind in register list.");
2803 case NoLanes:
2804 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2805 break;
2806 case AllLanes:
2807 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2808 S, E));
2809 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002810 case IndexedLane:
2811 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2812 LaneIndex, S, E));
2813 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002814 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002815 return MatchOperand_Success;
2816}
2817
Jim Grosbach43904292011-07-25 20:14:50 +00002818/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002819ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002820parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002821 SMLoc S = Parser.getTok().getLoc();
2822 const AsmToken &Tok = Parser.getTok();
2823 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2824 StringRef OptStr = Tok.getString();
2825
2826 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2827 .Case("sy", ARM_MB::SY)
2828 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002829 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002830 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002831 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002832 .Case("ishst", ARM_MB::ISHST)
2833 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002834 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002835 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002836 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002837 .Case("osh", ARM_MB::OSH)
2838 .Case("oshst", ARM_MB::OSHST)
2839 .Default(~0U);
2840
2841 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002842 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002843
2844 Parser.Lex(); // Eat identifier token.
2845 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002846 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002847}
2848
Jim Grosbach43904292011-07-25 20:14:50 +00002849/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002850ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002851parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002852 SMLoc S = Parser.getTok().getLoc();
2853 const AsmToken &Tok = Parser.getTok();
2854 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2855 StringRef IFlagsStr = Tok.getString();
2856
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002857 // An iflags string of "none" is interpreted to mean that none of the AIF
2858 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002859 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002860 if (IFlagsStr != "none") {
2861 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2862 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2863 .Case("a", ARM_PROC::A)
2864 .Case("i", ARM_PROC::I)
2865 .Case("f", ARM_PROC::F)
2866 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002867
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002868 // If some specific iflag is already set, it means that some letter is
2869 // present more than once, this is not acceptable.
2870 if (Flag == ~0U || (IFlags & Flag))
2871 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002872
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002873 IFlags |= Flag;
2874 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002875 }
2876
2877 Parser.Lex(); // Eat identifier token.
2878 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2879 return MatchOperand_Success;
2880}
2881
Jim Grosbach43904292011-07-25 20:14:50 +00002882/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002883ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002884parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002885 SMLoc S = Parser.getTok().getLoc();
2886 const AsmToken &Tok = Parser.getTok();
2887 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2888 StringRef Mask = Tok.getString();
2889
James Molloyacad68d2011-09-28 14:21:38 +00002890 if (isMClass()) {
2891 // See ARMv6-M 10.1.1
2892 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2893 .Case("apsr", 0)
2894 .Case("iapsr", 1)
2895 .Case("eapsr", 2)
2896 .Case("xpsr", 3)
2897 .Case("ipsr", 5)
2898 .Case("epsr", 6)
2899 .Case("iepsr", 7)
2900 .Case("msp", 8)
2901 .Case("psp", 9)
2902 .Case("primask", 16)
2903 .Case("basepri", 17)
2904 .Case("basepri_max", 18)
2905 .Case("faultmask", 19)
2906 .Case("control", 20)
2907 .Default(~0U);
2908
2909 if (FlagsVal == ~0U)
2910 return MatchOperand_NoMatch;
2911
2912 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2913 // basepri, basepri_max and faultmask only valid for V7m.
2914 return MatchOperand_NoMatch;
2915
2916 Parser.Lex(); // Eat identifier token.
2917 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2918 return MatchOperand_Success;
2919 }
2920
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002921 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2922 size_t Start = 0, Next = Mask.find('_');
2923 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002924 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002925 if (Next != StringRef::npos)
2926 Flags = Mask.slice(Next+1, Mask.size());
2927
2928 // FlagsVal contains the complete mask:
2929 // 3-0: Mask
2930 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2931 unsigned FlagsVal = 0;
2932
2933 if (SpecReg == "apsr") {
2934 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002935 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002936 .Case("g", 0x4) // same as CPSR_s
2937 .Case("nzcvqg", 0xc) // same as CPSR_fs
2938 .Default(~0U);
2939
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002940 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002941 if (!Flags.empty())
2942 return MatchOperand_NoMatch;
2943 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002944 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002945 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002946 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002947 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2948 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002949 for (int i = 0, e = Flags.size(); i != e; ++i) {
2950 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2951 .Case("c", 1)
2952 .Case("x", 2)
2953 .Case("s", 4)
2954 .Case("f", 8)
2955 .Default(~0U);
2956
2957 // If some specific flag is already set, it means that some letter is
2958 // present more than once, this is not acceptable.
2959 if (FlagsVal == ~0U || (FlagsVal & Flag))
2960 return MatchOperand_NoMatch;
2961 FlagsVal |= Flag;
2962 }
2963 } else // No match for special register.
2964 return MatchOperand_NoMatch;
2965
Owen Anderson7784f1d2011-10-21 18:43:28 +00002966 // Special register without flags is NOT equivalent to "fc" flags.
2967 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2968 // two lines would enable gas compatibility at the expense of breaking
2969 // round-tripping.
2970 //
2971 // if (!FlagsVal)
2972 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002973
2974 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2975 if (SpecReg == "spsr")
2976 FlagsVal |= 16;
2977
2978 Parser.Lex(); // Eat identifier token.
2979 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2980 return MatchOperand_Success;
2981}
2982
Jim Grosbachf6c05252011-07-21 17:23:04 +00002983ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2984parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2985 int Low, int High) {
2986 const AsmToken &Tok = Parser.getTok();
2987 if (Tok.isNot(AsmToken::Identifier)) {
2988 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2989 return MatchOperand_ParseFail;
2990 }
2991 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002992 std::string LowerOp = Op.lower();
2993 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002994 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2995 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2996 return MatchOperand_ParseFail;
2997 }
2998 Parser.Lex(); // Eat shift type token.
2999
3000 // There must be a '#' and a shift amount.
3001 if (Parser.getTok().isNot(AsmToken::Hash)) {
3002 Error(Parser.getTok().getLoc(), "'#' expected");
3003 return MatchOperand_ParseFail;
3004 }
3005 Parser.Lex(); // Eat hash token.
3006
3007 const MCExpr *ShiftAmount;
3008 SMLoc Loc = Parser.getTok().getLoc();
3009 if (getParser().ParseExpression(ShiftAmount)) {
3010 Error(Loc, "illegal expression");
3011 return MatchOperand_ParseFail;
3012 }
3013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3014 if (!CE) {
3015 Error(Loc, "constant expression expected");
3016 return MatchOperand_ParseFail;
3017 }
3018 int Val = CE->getValue();
3019 if (Val < Low || Val > High) {
3020 Error(Loc, "immediate value out of range");
3021 return MatchOperand_ParseFail;
3022 }
3023
3024 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3025
3026 return MatchOperand_Success;
3027}
3028
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003029ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3030parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3031 const AsmToken &Tok = Parser.getTok();
3032 SMLoc S = Tok.getLoc();
3033 if (Tok.isNot(AsmToken::Identifier)) {
3034 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3035 return MatchOperand_ParseFail;
3036 }
3037 int Val = StringSwitch<int>(Tok.getString())
3038 .Case("be", 1)
3039 .Case("le", 0)
3040 .Default(-1);
3041 Parser.Lex(); // Eat the token.
3042
3043 if (Val == -1) {
3044 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3045 return MatchOperand_ParseFail;
3046 }
3047 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3048 getContext()),
3049 S, Parser.getTok().getLoc()));
3050 return MatchOperand_Success;
3051}
3052
Jim Grosbach580f4a92011-07-25 22:20:28 +00003053/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3054/// instructions. Legal values are:
3055/// lsl #n 'n' in [0,31]
3056/// asr #n 'n' in [1,32]
3057/// n == 32 encoded as n == 0.
3058ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3059parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3060 const AsmToken &Tok = Parser.getTok();
3061 SMLoc S = Tok.getLoc();
3062 if (Tok.isNot(AsmToken::Identifier)) {
3063 Error(S, "shift operator 'asr' or 'lsl' expected");
3064 return MatchOperand_ParseFail;
3065 }
3066 StringRef ShiftName = Tok.getString();
3067 bool isASR;
3068 if (ShiftName == "lsl" || ShiftName == "LSL")
3069 isASR = false;
3070 else if (ShiftName == "asr" || ShiftName == "ASR")
3071 isASR = true;
3072 else {
3073 Error(S, "shift operator 'asr' or 'lsl' expected");
3074 return MatchOperand_ParseFail;
3075 }
3076 Parser.Lex(); // Eat the operator.
3077
3078 // A '#' and a shift amount.
3079 if (Parser.getTok().isNot(AsmToken::Hash)) {
3080 Error(Parser.getTok().getLoc(), "'#' expected");
3081 return MatchOperand_ParseFail;
3082 }
3083 Parser.Lex(); // Eat hash token.
3084
3085 const MCExpr *ShiftAmount;
3086 SMLoc E = Parser.getTok().getLoc();
3087 if (getParser().ParseExpression(ShiftAmount)) {
3088 Error(E, "malformed shift expression");
3089 return MatchOperand_ParseFail;
3090 }
3091 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3092 if (!CE) {
3093 Error(E, "shift amount must be an immediate");
3094 return MatchOperand_ParseFail;
3095 }
3096
3097 int64_t Val = CE->getValue();
3098 if (isASR) {
3099 // Shift amount must be in [1,32]
3100 if (Val < 1 || Val > 32) {
3101 Error(E, "'asr' shift amount must be in range [1,32]");
3102 return MatchOperand_ParseFail;
3103 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003104 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3105 if (isThumb() && Val == 32) {
3106 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3107 return MatchOperand_ParseFail;
3108 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003109 if (Val == 32) Val = 0;
3110 } else {
3111 // Shift amount must be in [1,32]
3112 if (Val < 0 || Val > 31) {
3113 Error(E, "'lsr' shift amount must be in range [0,31]");
3114 return MatchOperand_ParseFail;
3115 }
3116 }
3117
3118 E = Parser.getTok().getLoc();
3119 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3120
3121 return MatchOperand_Success;
3122}
3123
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003124/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3125/// of instructions. Legal values are:
3126/// ror #n 'n' in {0, 8, 16, 24}
3127ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3128parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3129 const AsmToken &Tok = Parser.getTok();
3130 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003131 if (Tok.isNot(AsmToken::Identifier))
3132 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003133 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003134 if (ShiftName != "ror" && ShiftName != "ROR")
3135 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003136 Parser.Lex(); // Eat the operator.
3137
3138 // A '#' and a rotate amount.
3139 if (Parser.getTok().isNot(AsmToken::Hash)) {
3140 Error(Parser.getTok().getLoc(), "'#' expected");
3141 return MatchOperand_ParseFail;
3142 }
3143 Parser.Lex(); // Eat hash token.
3144
3145 const MCExpr *ShiftAmount;
3146 SMLoc E = Parser.getTok().getLoc();
3147 if (getParser().ParseExpression(ShiftAmount)) {
3148 Error(E, "malformed rotate expression");
3149 return MatchOperand_ParseFail;
3150 }
3151 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3152 if (!CE) {
3153 Error(E, "rotate amount must be an immediate");
3154 return MatchOperand_ParseFail;
3155 }
3156
3157 int64_t Val = CE->getValue();
3158 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3159 // normally, zero is represented in asm by omitting the rotate operand
3160 // entirely.
3161 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3162 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3163 return MatchOperand_ParseFail;
3164 }
3165
3166 E = Parser.getTok().getLoc();
3167 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3168
3169 return MatchOperand_Success;
3170}
3171
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003172ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3173parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3174 SMLoc S = Parser.getTok().getLoc();
3175 // The bitfield descriptor is really two operands, the LSB and the width.
3176 if (Parser.getTok().isNot(AsmToken::Hash)) {
3177 Error(Parser.getTok().getLoc(), "'#' expected");
3178 return MatchOperand_ParseFail;
3179 }
3180 Parser.Lex(); // Eat hash token.
3181
3182 const MCExpr *LSBExpr;
3183 SMLoc E = Parser.getTok().getLoc();
3184 if (getParser().ParseExpression(LSBExpr)) {
3185 Error(E, "malformed immediate expression");
3186 return MatchOperand_ParseFail;
3187 }
3188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3189 if (!CE) {
3190 Error(E, "'lsb' operand must be an immediate");
3191 return MatchOperand_ParseFail;
3192 }
3193
3194 int64_t LSB = CE->getValue();
3195 // The LSB must be in the range [0,31]
3196 if (LSB < 0 || LSB > 31) {
3197 Error(E, "'lsb' operand must be in the range [0,31]");
3198 return MatchOperand_ParseFail;
3199 }
3200 E = Parser.getTok().getLoc();
3201
3202 // Expect another immediate operand.
3203 if (Parser.getTok().isNot(AsmToken::Comma)) {
3204 Error(Parser.getTok().getLoc(), "too few operands");
3205 return MatchOperand_ParseFail;
3206 }
3207 Parser.Lex(); // Eat hash token.
3208 if (Parser.getTok().isNot(AsmToken::Hash)) {
3209 Error(Parser.getTok().getLoc(), "'#' expected");
3210 return MatchOperand_ParseFail;
3211 }
3212 Parser.Lex(); // Eat hash token.
3213
3214 const MCExpr *WidthExpr;
3215 if (getParser().ParseExpression(WidthExpr)) {
3216 Error(E, "malformed immediate expression");
3217 return MatchOperand_ParseFail;
3218 }
3219 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3220 if (!CE) {
3221 Error(E, "'width' operand must be an immediate");
3222 return MatchOperand_ParseFail;
3223 }
3224
3225 int64_t Width = CE->getValue();
3226 // The LSB must be in the range [1,32-lsb]
3227 if (Width < 1 || Width > 32 - LSB) {
3228 Error(E, "'width' operand must be in the range [1,32-lsb]");
3229 return MatchOperand_ParseFail;
3230 }
3231 E = Parser.getTok().getLoc();
3232
3233 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3234
3235 return MatchOperand_Success;
3236}
3237
Jim Grosbach7ce05792011-08-03 23:50:40 +00003238ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3239parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3240 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003241 // postidx_reg := '+' register {, shift}
3242 // | '-' register {, shift}
3243 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003244
3245 // This method must return MatchOperand_NoMatch without consuming any tokens
3246 // in the case where there is no match, as other alternatives take other
3247 // parse methods.
3248 AsmToken Tok = Parser.getTok();
3249 SMLoc S = Tok.getLoc();
3250 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003251 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003252 int Reg = -1;
3253 if (Tok.is(AsmToken::Plus)) {
3254 Parser.Lex(); // Eat the '+' token.
3255 haveEaten = true;
3256 } else if (Tok.is(AsmToken::Minus)) {
3257 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003258 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003259 haveEaten = true;
3260 }
3261 if (Parser.getTok().is(AsmToken::Identifier))
3262 Reg = tryParseRegister();
3263 if (Reg == -1) {
3264 if (!haveEaten)
3265 return MatchOperand_NoMatch;
3266 Error(Parser.getTok().getLoc(), "register expected");
3267 return MatchOperand_ParseFail;
3268 }
3269 SMLoc E = Parser.getTok().getLoc();
3270
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003271 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3272 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003273 if (Parser.getTok().is(AsmToken::Comma)) {
3274 Parser.Lex(); // Eat the ','.
3275 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3276 return MatchOperand_ParseFail;
3277 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003278
3279 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3280 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003281
3282 return MatchOperand_Success;
3283}
3284
Jim Grosbach251bf252011-08-10 21:56:18 +00003285ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3286parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3287 // Check for a post-index addressing register operand. Specifically:
3288 // am3offset := '+' register
3289 // | '-' register
3290 // | register
3291 // | # imm
3292 // | # + imm
3293 // | # - imm
3294
3295 // This method must return MatchOperand_NoMatch without consuming any tokens
3296 // in the case where there is no match, as other alternatives take other
3297 // parse methods.
3298 AsmToken Tok = Parser.getTok();
3299 SMLoc S = Tok.getLoc();
3300
3301 // Do immediates first, as we always parse those if we have a '#'.
3302 if (Parser.getTok().is(AsmToken::Hash)) {
3303 Parser.Lex(); // Eat the '#'.
3304 // Explicitly look for a '-', as we need to encode negative zero
3305 // differently.
3306 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3307 const MCExpr *Offset;
3308 if (getParser().ParseExpression(Offset))
3309 return MatchOperand_ParseFail;
3310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3311 if (!CE) {
3312 Error(S, "constant expression expected");
3313 return MatchOperand_ParseFail;
3314 }
3315 SMLoc E = Tok.getLoc();
3316 // Negative zero is encoded as the flag value INT32_MIN.
3317 int32_t Val = CE->getValue();
3318 if (isNegative && Val == 0)
3319 Val = INT32_MIN;
3320
3321 Operands.push_back(
3322 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3323
3324 return MatchOperand_Success;
3325 }
3326
3327
3328 bool haveEaten = false;
3329 bool isAdd = true;
3330 int Reg = -1;
3331 if (Tok.is(AsmToken::Plus)) {
3332 Parser.Lex(); // Eat the '+' token.
3333 haveEaten = true;
3334 } else if (Tok.is(AsmToken::Minus)) {
3335 Parser.Lex(); // Eat the '-' token.
3336 isAdd = false;
3337 haveEaten = true;
3338 }
3339 if (Parser.getTok().is(AsmToken::Identifier))
3340 Reg = tryParseRegister();
3341 if (Reg == -1) {
3342 if (!haveEaten)
3343 return MatchOperand_NoMatch;
3344 Error(Parser.getTok().getLoc(), "register expected");
3345 return MatchOperand_ParseFail;
3346 }
3347 SMLoc E = Parser.getTok().getLoc();
3348
3349 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3350 0, S, E));
3351
3352 return MatchOperand_Success;
3353}
3354
Jim Grosbacha77295d2011-09-08 22:07:06 +00003355/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3356/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3357/// when they refer multiple MIOperands inside a single one.
3358bool ARMAsmParser::
3359cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3360 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3361 // Rt, Rt2
3362 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3363 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3364 // Create a writeback register dummy placeholder.
3365 Inst.addOperand(MCOperand::CreateReg(0));
3366 // addr
3367 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3368 // pred
3369 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3370 return true;
3371}
3372
3373/// cvtT2StrdPre - Convert parsed operands to MCInst.
3374/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3375/// when they refer multiple MIOperands inside a single one.
3376bool ARMAsmParser::
3377cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3378 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3379 // Create a writeback register dummy placeholder.
3380 Inst.addOperand(MCOperand::CreateReg(0));
3381 // Rt, Rt2
3382 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3383 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3384 // addr
3385 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3386 // pred
3387 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3388 return true;
3389}
3390
Jim Grosbacheeec0252011-09-08 00:39:19 +00003391/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3392/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3393/// when they refer multiple MIOperands inside a single one.
3394bool ARMAsmParser::
3395cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3396 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3397 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3398
3399 // Create a writeback register dummy placeholder.
3400 Inst.addOperand(MCOperand::CreateImm(0));
3401
3402 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3403 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3404 return true;
3405}
3406
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003407/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3408/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3409/// when they refer multiple MIOperands inside a single one.
3410bool ARMAsmParser::
3411cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3412 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3413 // Create a writeback register dummy placeholder.
3414 Inst.addOperand(MCOperand::CreateImm(0));
3415 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3416 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3417 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3418 return true;
3419}
3420
Jim Grosbach1355cf12011-07-26 17:10:22 +00003421/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003422/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3423/// when they refer multiple MIOperands inside a single one.
3424bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003425cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003426 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3427 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3428
3429 // Create a writeback register dummy placeholder.
3430 Inst.addOperand(MCOperand::CreateImm(0));
3431
Jim Grosbach7ce05792011-08-03 23:50:40 +00003432 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003433 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3434 return true;
3435}
3436
Owen Anderson9ab0f252011-08-26 20:43:14 +00003437/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3438/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3439/// when they refer multiple MIOperands inside a single one.
3440bool ARMAsmParser::
3441cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3442 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3443 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3444
3445 // Create a writeback register dummy placeholder.
3446 Inst.addOperand(MCOperand::CreateImm(0));
3447
3448 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3449 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3450 return true;
3451}
3452
3453
Jim Grosbach548340c2011-08-11 19:22:40 +00003454/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3455/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3456/// when they refer multiple MIOperands inside a single one.
3457bool ARMAsmParser::
3458cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3459 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3460 // Create a writeback register dummy placeholder.
3461 Inst.addOperand(MCOperand::CreateImm(0));
3462 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3463 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3464 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3465 return true;
3466}
3467
Jim Grosbach1355cf12011-07-26 17:10:22 +00003468/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003469/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3470/// when they refer multiple MIOperands inside a single one.
3471bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003472cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003473 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3474 // Create a writeback register dummy placeholder.
3475 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003476 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3477 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3478 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003479 return true;
3480}
3481
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003482/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3483/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3484/// when they refer multiple MIOperands inside a single one.
3485bool ARMAsmParser::
3486cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3487 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3488 // Create a writeback register dummy placeholder.
3489 Inst.addOperand(MCOperand::CreateImm(0));
3490 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3491 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3492 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3493 return true;
3494}
3495
Jim Grosbach7ce05792011-08-03 23:50:40 +00003496/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3497/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3498/// when they refer multiple MIOperands inside a single one.
3499bool ARMAsmParser::
3500cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3501 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3502 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003503 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003504 // Create a writeback register dummy placeholder.
3505 Inst.addOperand(MCOperand::CreateImm(0));
3506 // addr
3507 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3508 // offset
3509 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3510 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003511 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3512 return true;
3513}
3514
Jim Grosbach7ce05792011-08-03 23:50:40 +00003515/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003516/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3517/// when they refer multiple MIOperands inside a single one.
3518bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003519cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3520 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3521 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003522 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003523 // Create a writeback register dummy placeholder.
3524 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003525 // addr
3526 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3527 // offset
3528 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3529 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003530 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3531 return true;
3532}
3533
Jim Grosbach7ce05792011-08-03 23:50:40 +00003534/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003535/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3536/// when they refer multiple MIOperands inside a single one.
3537bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003538cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3539 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003540 // Create a writeback register dummy placeholder.
3541 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003542 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003543 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003544 // addr
3545 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3546 // offset
3547 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3548 // pred
3549 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3550 return true;
3551}
3552
3553/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3554/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3555/// when they refer multiple MIOperands inside a single one.
3556bool ARMAsmParser::
3557cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3558 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3559 // Create a writeback register dummy placeholder.
3560 Inst.addOperand(MCOperand::CreateImm(0));
3561 // Rt
3562 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3563 // addr
3564 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3565 // offset
3566 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3567 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003568 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3569 return true;
3570}
3571
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003572/// cvtLdrdPre - Convert parsed operands to MCInst.
3573/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3574/// when they refer multiple MIOperands inside a single one.
3575bool ARMAsmParser::
3576cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3577 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3578 // Rt, Rt2
3579 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3580 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3581 // Create a writeback register dummy placeholder.
3582 Inst.addOperand(MCOperand::CreateImm(0));
3583 // addr
3584 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3585 // pred
3586 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3587 return true;
3588}
3589
Jim Grosbach14605d12011-08-11 20:28:23 +00003590/// cvtStrdPre - Convert parsed operands to MCInst.
3591/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3592/// when they refer multiple MIOperands inside a single one.
3593bool ARMAsmParser::
3594cvtStrdPre(MCInst &Inst, unsigned Opcode,
3595 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3596 // Create a writeback register dummy placeholder.
3597 Inst.addOperand(MCOperand::CreateImm(0));
3598 // Rt, Rt2
3599 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3600 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3601 // addr
3602 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3603 // pred
3604 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3605 return true;
3606}
3607
Jim Grosbach623a4542011-08-10 22:42:16 +00003608/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3609/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3610/// when they refer multiple MIOperands inside a single one.
3611bool ARMAsmParser::
3612cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3613 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3614 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3615 // Create a writeback register dummy placeholder.
3616 Inst.addOperand(MCOperand::CreateImm(0));
3617 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3618 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3619 return true;
3620}
3621
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003622/// cvtThumbMultiple- Convert parsed operands to MCInst.
3623/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3624/// when they refer multiple MIOperands inside a single one.
3625bool ARMAsmParser::
3626cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3627 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3628 // The second source operand must be the same register as the destination
3629 // operand.
3630 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003631 (((ARMOperand*)Operands[3])->getReg() !=
3632 ((ARMOperand*)Operands[5])->getReg()) &&
3633 (((ARMOperand*)Operands[3])->getReg() !=
3634 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003635 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003636 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003637 return false;
3638 }
3639 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3640 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003641 // If we have a three-operand form, make sure to set Rn to be the operand
3642 // that isn't the same as Rd.
3643 unsigned RegOp = 4;
3644 if (Operands.size() == 6 &&
3645 ((ARMOperand*)Operands[4])->getReg() ==
3646 ((ARMOperand*)Operands[3])->getReg())
3647 RegOp = 5;
3648 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3649 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003650 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3651
3652 return true;
3653}
Jim Grosbach623a4542011-08-10 22:42:16 +00003654
Jim Grosbach12431322011-10-24 22:16:58 +00003655bool ARMAsmParser::
3656cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3657 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3658 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003659 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003660 // Create a writeback register dummy placeholder.
3661 Inst.addOperand(MCOperand::CreateImm(0));
3662 // Vn
3663 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3664 // pred
3665 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3666 return true;
3667}
3668
3669bool ARMAsmParser::
3670cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3671 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3672 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003673 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003674 // Create a writeback register dummy placeholder.
3675 Inst.addOperand(MCOperand::CreateImm(0));
3676 // Vn
3677 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3678 // Vm
3679 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3680 // pred
3681 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3682 return true;
3683}
3684
Jim Grosbach4334e032011-10-31 21:50:31 +00003685bool ARMAsmParser::
3686cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3687 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3688 // Create a writeback register dummy placeholder.
3689 Inst.addOperand(MCOperand::CreateImm(0));
3690 // Vn
3691 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3692 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003693 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003694 // pred
3695 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3696 return true;
3697}
3698
3699bool ARMAsmParser::
3700cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3701 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3702 // Create a writeback register dummy placeholder.
3703 Inst.addOperand(MCOperand::CreateImm(0));
3704 // Vn
3705 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3706 // Vm
3707 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3708 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003709 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003710 // pred
3711 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3712 return true;
3713}
3714
Bill Wendlinge7176102010-11-06 22:36:58 +00003715/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003716/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003717bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003718parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003719 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003720 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003721 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003722 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003723 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003724
Sean Callanan18b83232010-01-19 21:44:56 +00003725 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003726 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003727 if (BaseRegNum == -1)
3728 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003729
Daniel Dunbar05710932011-01-18 05:34:17 +00003730 // The next token must either be a comma or a closing bracket.
3731 const AsmToken &Tok = Parser.getTok();
3732 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003733 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003734
Jim Grosbach7ce05792011-08-03 23:50:40 +00003735 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003736 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003737 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003738
Jim Grosbach7ce05792011-08-03 23:50:40 +00003739 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003740 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003741
Jim Grosbachfb12f352011-09-19 18:42:21 +00003742 // If there's a pre-indexing writeback marker, '!', just add it as a token
3743 // operand. It's rather odd, but syntactically valid.
3744 if (Parser.getTok().is(AsmToken::Exclaim)) {
3745 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3746 Parser.Lex(); // Eat the '!'.
3747 }
3748
Jim Grosbach7ce05792011-08-03 23:50:40 +00003749 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003750 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003751
Jim Grosbach7ce05792011-08-03 23:50:40 +00003752 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3753 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003754
Jim Grosbach57dcb852011-10-11 17:29:55 +00003755 // If we have a ':', it's an alignment specifier.
3756 if (Parser.getTok().is(AsmToken::Colon)) {
3757 Parser.Lex(); // Eat the ':'.
3758 E = Parser.getTok().getLoc();
3759
3760 const MCExpr *Expr;
3761 if (getParser().ParseExpression(Expr))
3762 return true;
3763
3764 // The expression has to be a constant. Memory references with relocations
3765 // don't come through here, as they use the <label> forms of the relevant
3766 // instructions.
3767 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3768 if (!CE)
3769 return Error (E, "constant expression expected");
3770
3771 unsigned Align = 0;
3772 switch (CE->getValue()) {
3773 default:
3774 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3775 case 64: Align = 8; break;
3776 case 128: Align = 16; break;
3777 case 256: Align = 32; break;
3778 }
3779
3780 // Now we should have the closing ']'
3781 E = Parser.getTok().getLoc();
3782 if (Parser.getTok().isNot(AsmToken::RBrac))
3783 return Error(E, "']' expected");
3784 Parser.Lex(); // Eat right bracket token.
3785
3786 // Don't worry about range checking the value here. That's handled by
3787 // the is*() predicates.
3788 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3789 ARM_AM::no_shift, 0, Align,
3790 false, S, E));
3791
3792 // If there's a pre-indexing writeback marker, '!', just add it as a token
3793 // operand.
3794 if (Parser.getTok().is(AsmToken::Exclaim)) {
3795 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3796 Parser.Lex(); // Eat the '!'.
3797 }
3798
3799 return false;
3800 }
3801
3802 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003803 // offset. Be friendly and also accept a plain integer (without a leading
3804 // hash) for gas compatibility.
3805 if (Parser.getTok().is(AsmToken::Hash) ||
3806 Parser.getTok().is(AsmToken::Integer)) {
3807 if (Parser.getTok().is(AsmToken::Hash))
3808 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003809 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003810
Owen Anderson0da10cf2011-08-29 19:36:44 +00003811 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003812 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003813 if (getParser().ParseExpression(Offset))
3814 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003815
3816 // The expression has to be a constant. Memory references with relocations
3817 // don't come through here, as they use the <label> forms of the relevant
3818 // instructions.
3819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3820 if (!CE)
3821 return Error (E, "constant expression expected");
3822
Owen Anderson0da10cf2011-08-29 19:36:44 +00003823 // If the constant was #-0, represent it as INT32_MIN.
3824 int32_t Val = CE->getValue();
3825 if (isNegative && Val == 0)
3826 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3827
Jim Grosbach7ce05792011-08-03 23:50:40 +00003828 // Now we should have the closing ']'
3829 E = Parser.getTok().getLoc();
3830 if (Parser.getTok().isNot(AsmToken::RBrac))
3831 return Error(E, "']' expected");
3832 Parser.Lex(); // Eat right bracket token.
3833
3834 // Don't worry about range checking the value here. That's handled by
3835 // the is*() predicates.
3836 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003837 ARM_AM::no_shift, 0, 0,
3838 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003839
3840 // If there's a pre-indexing writeback marker, '!', just add it as a token
3841 // operand.
3842 if (Parser.getTok().is(AsmToken::Exclaim)) {
3843 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3844 Parser.Lex(); // Eat the '!'.
3845 }
3846
3847 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003848 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003849
3850 // The register offset is optionally preceded by a '+' or '-'
3851 bool isNegative = false;
3852 if (Parser.getTok().is(AsmToken::Minus)) {
3853 isNegative = true;
3854 Parser.Lex(); // Eat the '-'.
3855 } else if (Parser.getTok().is(AsmToken::Plus)) {
3856 // Nothing to do.
3857 Parser.Lex(); // Eat the '+'.
3858 }
3859
3860 E = Parser.getTok().getLoc();
3861 int OffsetRegNum = tryParseRegister();
3862 if (OffsetRegNum == -1)
3863 return Error(E, "register expected");
3864
3865 // If there's a shift operator, handle it.
3866 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003867 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003868 if (Parser.getTok().is(AsmToken::Comma)) {
3869 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003870 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003871 return true;
3872 }
3873
3874 // Now we should have the closing ']'
3875 E = Parser.getTok().getLoc();
3876 if (Parser.getTok().isNot(AsmToken::RBrac))
3877 return Error(E, "']' expected");
3878 Parser.Lex(); // Eat right bracket token.
3879
3880 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003881 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003882 S, E));
3883
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003884 // If there's a pre-indexing writeback marker, '!', just add it as a token
3885 // operand.
3886 if (Parser.getTok().is(AsmToken::Exclaim)) {
3887 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3888 Parser.Lex(); // Eat the '!'.
3889 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003890
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003891 return false;
3892}
3893
Jim Grosbach7ce05792011-08-03 23:50:40 +00003894/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003895/// ( lsl | lsr | asr | ror ) , # shift_amount
3896/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003897/// return true if it parses a shift otherwise it returns false.
3898bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3899 unsigned &Amount) {
3900 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003901 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003902 if (Tok.isNot(AsmToken::Identifier))
3903 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003904 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00003905 if (ShiftName == "lsl" || ShiftName == "LSL" ||
3906 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00003907 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003908 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003909 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003910 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003911 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003912 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003913 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003914 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003915 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003916 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003917 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003918 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003919
Jim Grosbach7ce05792011-08-03 23:50:40 +00003920 // rrx stands alone.
3921 Amount = 0;
3922 if (St != ARM_AM::rrx) {
3923 Loc = Parser.getTok().getLoc();
3924 // A '#' and a shift amount.
3925 const AsmToken &HashTok = Parser.getTok();
3926 if (HashTok.isNot(AsmToken::Hash))
3927 return Error(HashTok.getLoc(), "'#' expected");
3928 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003929
Jim Grosbach7ce05792011-08-03 23:50:40 +00003930 const MCExpr *Expr;
3931 if (getParser().ParseExpression(Expr))
3932 return true;
3933 // Range check the immediate.
3934 // lsl, ror: 0 <= imm <= 31
3935 // lsr, asr: 0 <= imm <= 32
3936 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3937 if (!CE)
3938 return Error(Loc, "shift amount must be an immediate");
3939 int64_t Imm = CE->getValue();
3940 if (Imm < 0 ||
3941 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3942 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3943 return Error(Loc, "immediate shift value out of range");
3944 Amount = Imm;
3945 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003946
3947 return false;
3948}
3949
Jim Grosbach9d390362011-10-03 23:38:36 +00003950/// parseFPImm - A floating point immediate expression operand.
3951ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3952parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3953 SMLoc S = Parser.getTok().getLoc();
3954
3955 if (Parser.getTok().isNot(AsmToken::Hash))
3956 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003957
3958 // Disambiguate the VMOV forms that can accept an FP immediate.
3959 // vmov.f32 <sreg>, #imm
3960 // vmov.f64 <dreg>, #imm
3961 // vmov.f32 <dreg>, #imm @ vector f32x2
3962 // vmov.f32 <qreg>, #imm @ vector f32x4
3963 //
3964 // There are also the NEON VMOV instructions which expect an
3965 // integer constant. Make sure we don't try to parse an FPImm
3966 // for these:
3967 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3968 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3969 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3970 TyOp->getToken() != ".f64"))
3971 return MatchOperand_NoMatch;
3972
Jim Grosbach9d390362011-10-03 23:38:36 +00003973 Parser.Lex(); // Eat the '#'.
3974
3975 // Handle negation, as that still comes through as a separate token.
3976 bool isNegative = false;
3977 if (Parser.getTok().is(AsmToken::Minus)) {
3978 isNegative = true;
3979 Parser.Lex();
3980 }
3981 const AsmToken &Tok = Parser.getTok();
3982 if (Tok.is(AsmToken::Real)) {
3983 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3984 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3985 // If we had a '-' in front, toggle the sign bit.
3986 IntVal ^= (uint64_t)isNegative << 63;
3987 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3988 Parser.Lex(); // Eat the token.
3989 if (Val == -1) {
3990 TokError("floating point value out of range");
3991 return MatchOperand_ParseFail;
3992 }
3993 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3994 return MatchOperand_Success;
3995 }
3996 if (Tok.is(AsmToken::Integer)) {
3997 int64_t Val = Tok.getIntVal();
3998 Parser.Lex(); // Eat the token.
3999 if (Val > 255 || Val < 0) {
4000 TokError("encoded floating point value out of range");
4001 return MatchOperand_ParseFail;
4002 }
4003 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4004 return MatchOperand_Success;
4005 }
4006
4007 TokError("invalid floating point immediate");
4008 return MatchOperand_ParseFail;
4009}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004010/// Parse a arm instruction operand. For now this parses the operand regardless
4011/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004012bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004013 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004014 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004015
4016 // Check if the current operand has a custom associated parser, if so, try to
4017 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004018 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4019 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004020 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004021 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4022 // there was a match, but an error occurred, in which case, just return that
4023 // the operand parsing failed.
4024 if (ResTy == MatchOperand_ParseFail)
4025 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004026
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004027 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004028 default:
4029 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004030 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004031 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004032 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004033 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004034 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004035 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004036 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004037 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004038 else if (Res == -1) // irrecoverable error
4039 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004040 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4041 S = Parser.getTok().getLoc();
4042 Parser.Lex();
4043 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4044 return false;
4045 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004046
4047 // Fall though for the Identifier case that is not a register or a
4048 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004049 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004050 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004051 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004052 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004053 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004054 // This was not a register so parse other operands that start with an
4055 // identifier (like labels) as expressions and create them as immediates.
4056 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004057 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004058 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004059 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004060 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004061 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4062 return false;
4063 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004064 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004065 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004066 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004067 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004068 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004069 // #42 -> immediate.
4070 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004071 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004072 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004073 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004074 const MCExpr *ImmVal;
4075 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004076 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004077 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004078 if (CE) {
4079 int32_t Val = CE->getValue();
4080 if (isNegative && Val == 0)
4081 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004082 }
Sean Callanan76264762010-04-02 22:27:05 +00004083 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004084 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4085 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004086 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004087 case AsmToken::Colon: {
4088 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004089 // FIXME: Check it's an expression prefix,
4090 // e.g. (FOO - :lower16:BAR) isn't legal.
4091 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004092 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004093 return true;
4094
Evan Cheng75972122011-01-13 07:58:56 +00004095 const MCExpr *SubExprVal;
4096 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004097 return true;
4098
Evan Cheng75972122011-01-13 07:58:56 +00004099 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4100 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004101 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004102 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004103 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004104 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004105 }
4106}
4107
Jim Grosbach1355cf12011-07-26 17:10:22 +00004108// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004109// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004110bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004111 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004112
4113 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004114 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004115 Parser.Lex(); // Eat ':'
4116
4117 if (getLexer().isNot(AsmToken::Identifier)) {
4118 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4119 return true;
4120 }
4121
4122 StringRef IDVal = Parser.getTok().getIdentifier();
4123 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004124 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004125 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004126 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004127 } else {
4128 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4129 return true;
4130 }
4131 Parser.Lex();
4132
4133 if (getLexer().isNot(AsmToken::Colon)) {
4134 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4135 return true;
4136 }
4137 Parser.Lex(); // Eat the last ':'
4138 return false;
4139}
4140
Daniel Dunbar352e1482011-01-11 15:59:50 +00004141/// \brief Given a mnemonic, split out possible predication code and carry
4142/// setting letters to form a canonical mnemonic and flags.
4143//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004144// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004145// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004146StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004147 unsigned &PredicationCode,
4148 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004149 unsigned &ProcessorIMod,
4150 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004151 PredicationCode = ARMCC::AL;
4152 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004153 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004154
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004155 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004156 //
4157 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004158 if ((Mnemonic == "movs" && isThumb()) ||
4159 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4160 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4161 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4162 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4163 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4164 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4165 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004166 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004167
Jim Grosbach3f00e312011-07-11 17:09:57 +00004168 // First, split out any predication code. Ignore mnemonics we know aren't
4169 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004170 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004171 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004172 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004173 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004174 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4175 .Case("eq", ARMCC::EQ)
4176 .Case("ne", ARMCC::NE)
4177 .Case("hs", ARMCC::HS)
4178 .Case("cs", ARMCC::HS)
4179 .Case("lo", ARMCC::LO)
4180 .Case("cc", ARMCC::LO)
4181 .Case("mi", ARMCC::MI)
4182 .Case("pl", ARMCC::PL)
4183 .Case("vs", ARMCC::VS)
4184 .Case("vc", ARMCC::VC)
4185 .Case("hi", ARMCC::HI)
4186 .Case("ls", ARMCC::LS)
4187 .Case("ge", ARMCC::GE)
4188 .Case("lt", ARMCC::LT)
4189 .Case("gt", ARMCC::GT)
4190 .Case("le", ARMCC::LE)
4191 .Case("al", ARMCC::AL)
4192 .Default(~0U);
4193 if (CC != ~0U) {
4194 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4195 PredicationCode = CC;
4196 }
Bill Wendling52925b62010-10-29 23:50:21 +00004197 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004198
Daniel Dunbar352e1482011-01-11 15:59:50 +00004199 // Next, determine if we have a carry setting bit. We explicitly ignore all
4200 // the instructions we know end in 's'.
4201 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004202 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004203 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4204 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4205 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004206 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4207 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004208 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4209 CarrySetting = true;
4210 }
4211
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004212 // The "cps" instruction can have a interrupt mode operand which is glued into
4213 // the mnemonic. Check if this is the case, split it and parse the imod op
4214 if (Mnemonic.startswith("cps")) {
4215 // Split out any imod code.
4216 unsigned IMod =
4217 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4218 .Case("ie", ARM_PROC::IE)
4219 .Case("id", ARM_PROC::ID)
4220 .Default(~0U);
4221 if (IMod != ~0U) {
4222 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4223 ProcessorIMod = IMod;
4224 }
4225 }
4226
Jim Grosbach89df9962011-08-26 21:43:41 +00004227 // The "it" instruction has the condition mask on the end of the mnemonic.
4228 if (Mnemonic.startswith("it")) {
4229 ITMask = Mnemonic.slice(2, Mnemonic.size());
4230 Mnemonic = Mnemonic.slice(0, 2);
4231 }
4232
Daniel Dunbar352e1482011-01-11 15:59:50 +00004233 return Mnemonic;
4234}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004235
4236/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4237/// inclusion of carry set or predication code operands.
4238//
4239// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004240void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004241getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004242 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004243 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4244 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004245 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004246 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004247 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004248 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004249 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004250 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004251 Mnemonic == "mla" || Mnemonic == "smlal" ||
4252 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004253 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004254 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004255 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004256
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004257 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4258 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4259 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4260 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004261 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4262 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004263 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004264 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4265 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4266 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004267 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4268 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004269 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004270 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004271 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004272 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004273
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004274 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004275 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004276 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004277 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004278 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004279}
4280
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004281bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4282 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004283 // FIXME: This is all horribly hacky. We really need a better way to deal
4284 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004285
4286 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4287 // another does not. Specifically, the MOVW instruction does not. So we
4288 // special case it here and remove the defaulted (non-setting) cc_out
4289 // operand if that's the instruction we're trying to match.
4290 //
4291 // We do this as post-processing of the explicit operands rather than just
4292 // conditionally adding the cc_out in the first place because we need
4293 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004294 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004295 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4296 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4297 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4298 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004299
4300 // Register-register 'add' for thumb does not have a cc_out operand
4301 // when there are only two register operands.
4302 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4303 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4304 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4305 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4306 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004307 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004308 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4309 // have to check the immediate range here since Thumb2 has a variant
4310 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004311 if (((isThumb() && Mnemonic == "add") ||
4312 (isThumbTwo() && Mnemonic == "sub")) &&
4313 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004314 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4315 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4316 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004317 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4318 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4319 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004320 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004321 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4322 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004323 // selecting via the generic "add" mnemonic, so to know that we
4324 // should remove the cc_out operand, we have to explicitly check that
4325 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004326 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4327 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004328 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4329 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4330 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4331 // Nest conditions rather than one big 'if' statement for readability.
4332 //
4333 // If either register is a high reg, it's either one of the SP
4334 // variants (handled above) or a 32-bit encoding, so we just
4335 // check against T3.
4336 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4337 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4338 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4339 return false;
4340 // If both registers are low, we're in an IT block, and the immediate is
4341 // in range, we should use encoding T1 instead, which has a cc_out.
4342 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004343 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004344 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4345 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4346 return false;
4347
4348 // Otherwise, we use encoding T4, which does not have a cc_out
4349 // operand.
4350 return true;
4351 }
4352
Jim Grosbach64944f42011-09-14 21:00:40 +00004353 // The thumb2 multiply instruction doesn't have a CCOut register, so
4354 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4355 // use the 16-bit encoding or not.
4356 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4357 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4358 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4359 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4360 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4361 // If the registers aren't low regs, the destination reg isn't the
4362 // same as one of the source regs, or the cc_out operand is zero
4363 // outside of an IT block, we have to use the 32-bit encoding, so
4364 // remove the cc_out operand.
4365 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4366 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004367 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004368 !inITBlock() ||
4369 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4370 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4371 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4372 static_cast<ARMOperand*>(Operands[4])->getReg())))
4373 return true;
4374
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004375 // Also check the 'mul' syntax variant that doesn't specify an explicit
4376 // destination register.
4377 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4378 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4379 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4380 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4381 // If the registers aren't low regs or the cc_out operand is zero
4382 // outside of an IT block, we have to use the 32-bit encoding, so
4383 // remove the cc_out operand.
4384 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4385 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4386 !inITBlock()))
4387 return true;
4388
Jim Grosbach64944f42011-09-14 21:00:40 +00004389
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004390
Jim Grosbachf69c8042011-08-24 21:42:27 +00004391 // Register-register 'add/sub' for thumb does not have a cc_out operand
4392 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4393 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4394 // right, this will result in better diagnostics (which operand is off)
4395 // anyway.
4396 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4397 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004398 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4399 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4400 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4401 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004402
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004403 return false;
4404}
4405
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004406static bool isDataTypeToken(StringRef Tok) {
4407 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4408 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4409 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4410 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4411 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4412 Tok == ".f" || Tok == ".d";
4413}
4414
4415// FIXME: This bit should probably be handled via an explicit match class
4416// in the .td files that matches the suffix instead of having it be
4417// a literal string token the way it is now.
4418static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4419 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4420}
4421
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004422/// Parse an arm instruction mnemonic followed by its operands.
4423bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4424 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4425 // Create the leading tokens for the mnemonic, split by '.' characters.
4426 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004427 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004428
Daniel Dunbar352e1482011-01-11 15:59:50 +00004429 // Split out the predication code and carry setting flag from the mnemonic.
4430 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004431 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004432 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004433 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004434 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004435 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004436
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004437 // In Thumb1, only the branch (B) instruction can be predicated.
4438 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4439 Parser.EatToEndOfStatement();
4440 return Error(NameLoc, "conditional execution not supported in Thumb1");
4441 }
4442
Jim Grosbachffa32252011-07-19 19:13:28 +00004443 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4444
Jim Grosbach89df9962011-08-26 21:43:41 +00004445 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4446 // is the mask as it will be for the IT encoding if the conditional
4447 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4448 // where the conditional bit0 is zero, the instruction post-processing
4449 // will adjust the mask accordingly.
4450 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004451 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4452 if (ITMask.size() > 3) {
4453 Parser.EatToEndOfStatement();
4454 return Error(Loc, "too many conditions on IT instruction");
4455 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004456 unsigned Mask = 8;
4457 for (unsigned i = ITMask.size(); i != 0; --i) {
4458 char pos = ITMask[i - 1];
4459 if (pos != 't' && pos != 'e') {
4460 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004461 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004462 }
4463 Mask >>= 1;
4464 if (ITMask[i - 1] == 't')
4465 Mask |= 8;
4466 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004467 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004468 }
4469
Jim Grosbachffa32252011-07-19 19:13:28 +00004470 // FIXME: This is all a pretty gross hack. We should automatically handle
4471 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004472
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004473 // Next, add the CCOut and ConditionCode operands, if needed.
4474 //
4475 // For mnemonics which can ever incorporate a carry setting bit or predication
4476 // code, our matching model involves us always generating CCOut and
4477 // ConditionCode operands to match the mnemonic "as written" and then we let
4478 // the matcher deal with finding the right instruction or generating an
4479 // appropriate error.
4480 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004481 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004482
Jim Grosbach33c16a22011-07-14 22:04:21 +00004483 // If we had a carry-set on an instruction that can't do that, issue an
4484 // error.
4485 if (!CanAcceptCarrySet && CarrySetting) {
4486 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004487 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004488 "' can not set flags, but 's' suffix specified");
4489 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004490 // If we had a predication code on an instruction that can't do that, issue an
4491 // error.
4492 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4493 Parser.EatToEndOfStatement();
4494 return Error(NameLoc, "instruction '" + Mnemonic +
4495 "' is not predicable, but condition code specified");
4496 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004497
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004498 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004499 if (CanAcceptCarrySet) {
4500 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004501 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004502 Loc));
4503 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004504
4505 // Add the predication code operand, if necessary.
4506 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004507 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4508 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004509 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004510 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004511 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004512
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004513 // Add the processor imod operand, if necessary.
4514 if (ProcessorIMod) {
4515 Operands.push_back(ARMOperand::CreateImm(
4516 MCConstantExpr::Create(ProcessorIMod, getContext()),
4517 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004518 }
4519
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004520 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004521 while (Next != StringRef::npos) {
4522 Start = Next;
4523 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004524 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004525
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004526 // Some NEON instructions have an optional datatype suffix that is
4527 // completely ignored. Check for that.
4528 if (isDataTypeToken(ExtraToken) &&
4529 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4530 continue;
4531
Jim Grosbach81d2e392011-09-07 16:06:04 +00004532 if (ExtraToken != ".n") {
4533 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4534 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4535 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004536 }
4537
4538 // Read the remaining operands.
4539 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004540 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004541 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004542 Parser.EatToEndOfStatement();
4543 return true;
4544 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004545
4546 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004547 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004548
4549 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004550 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004551 Parser.EatToEndOfStatement();
4552 return true;
4553 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004554 }
4555 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004556
Chris Lattnercbf8a982010-09-11 16:18:25 +00004557 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004558 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004559 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004560 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004561 }
Bill Wendling146018f2010-11-06 21:42:12 +00004562
Chris Lattner34e53142010-09-08 05:10:46 +00004563 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004564
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004565 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4566 // do and don't have a cc_out optional-def operand. With some spot-checks
4567 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004568 // parse and adjust accordingly before actually matching. We shouldn't ever
4569 // try to remove a cc_out operand that was explicitly set on the the
4570 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4571 // table driven matcher doesn't fit well with the ARM instruction set.
4572 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004573 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4574 Operands.erase(Operands.begin() + 1);
4575 delete Op;
4576 }
4577
Jim Grosbachcf121c32011-07-28 21:57:55 +00004578 // ARM mode 'blx' need special handling, as the register operand version
4579 // is predicable, but the label operand version is not. So, we can't rely
4580 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004581 // a k_CondCode operand in the list. If we're trying to match the label
4582 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004583 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4584 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4585 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4586 Operands.erase(Operands.begin() + 1);
4587 delete Op;
4588 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004589
4590 // The vector-compare-to-zero instructions have a literal token "#0" at
4591 // the end that comes to here as an immediate operand. Convert it to a
4592 // token to play nicely with the matcher.
4593 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4594 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4595 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4596 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4598 if (CE && CE->getValue() == 0) {
4599 Operands.erase(Operands.begin() + 5);
4600 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4601 delete Op;
4602 }
4603 }
Jim Grosbach68259142011-10-03 22:30:24 +00004604 // VCMP{E} does the same thing, but with a different operand count.
4605 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4606 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4607 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4609 if (CE && CE->getValue() == 0) {
4610 Operands.erase(Operands.begin() + 4);
4611 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4612 delete Op;
4613 }
4614 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004615 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4616 // end. Convert it to a token here.
4617 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4618 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4619 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4620 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4621 if (CE && CE->getValue() == 0) {
4622 Operands.erase(Operands.begin() + 5);
4623 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4624 delete Op;
4625 }
4626 }
4627
Chris Lattner98986712010-01-14 22:21:20 +00004628 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004629}
4630
Jim Grosbach189610f2011-07-26 18:25:39 +00004631// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004632
4633// return 'true' if register list contains non-low GPR registers,
4634// 'false' otherwise. If Reg is in the register list or is HiReg, set
4635// 'containsReg' to true.
4636static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4637 unsigned HiReg, bool &containsReg) {
4638 containsReg = false;
4639 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4640 unsigned OpReg = Inst.getOperand(i).getReg();
4641 if (OpReg == Reg)
4642 containsReg = true;
4643 // Anything other than a low register isn't legal here.
4644 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4645 return true;
4646 }
4647 return false;
4648}
4649
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004650// Check if the specified regisgter is in the register list of the inst,
4651// starting at the indicated operand number.
4652static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4653 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4654 unsigned OpReg = Inst.getOperand(i).getReg();
4655 if (OpReg == Reg)
4656 return true;
4657 }
4658 return false;
4659}
4660
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004661// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4662// the ARMInsts array) instead. Getting that here requires awkward
4663// API changes, though. Better way?
4664namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004665extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004666}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004667static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004668 return ARMInsts[Opcode];
4669}
4670
Jim Grosbach189610f2011-07-26 18:25:39 +00004671// FIXME: We would really like to be able to tablegen'erate this.
4672bool ARMAsmParser::
4673validateInstruction(MCInst &Inst,
4674 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004675 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004676 SMLoc Loc = Operands[0]->getStartLoc();
4677 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004678 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4679 // being allowed in IT blocks, but not being predicable. It just always
4680 // executes.
4681 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004682 unsigned bit = 1;
4683 if (ITState.FirstCond)
4684 ITState.FirstCond = false;
4685 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004686 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004687 // The instruction must be predicable.
4688 if (!MCID.isPredicable())
4689 return Error(Loc, "instructions in IT block must be predicable");
4690 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4691 unsigned ITCond = bit ? ITState.Cond :
4692 ARMCC::getOppositeCondition(ITState.Cond);
4693 if (Cond != ITCond) {
4694 // Find the condition code Operand to get its SMLoc information.
4695 SMLoc CondLoc;
4696 for (unsigned i = 1; i < Operands.size(); ++i)
4697 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4698 CondLoc = Operands[i]->getStartLoc();
4699 return Error(CondLoc, "incorrect condition in IT block; got '" +
4700 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4701 "', but expected '" +
4702 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4703 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004704 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004705 } else if (isThumbTwo() && MCID.isPredicable() &&
4706 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004707 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4708 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004709 return Error(Loc, "predicated instructions must be in IT block");
4710
Jim Grosbach189610f2011-07-26 18:25:39 +00004711 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004712 case ARM::LDRD:
4713 case ARM::LDRD_PRE:
4714 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004715 case ARM::LDREXD: {
4716 // Rt2 must be Rt + 1.
4717 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4718 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4719 if (Rt2 != Rt + 1)
4720 return Error(Operands[3]->getStartLoc(),
4721 "destination operands must be sequential");
4722 return false;
4723 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004724 case ARM::STRD: {
4725 // Rt2 must be Rt + 1.
4726 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4727 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4728 if (Rt2 != Rt + 1)
4729 return Error(Operands[3]->getStartLoc(),
4730 "source operands must be sequential");
4731 return false;
4732 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004733 case ARM::STRD_PRE:
4734 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004735 case ARM::STREXD: {
4736 // Rt2 must be Rt + 1.
4737 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4738 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4739 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004740 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004741 "source operands must be sequential");
4742 return false;
4743 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004744 case ARM::SBFX:
4745 case ARM::UBFX: {
4746 // width must be in range [1, 32-lsb]
4747 unsigned lsb = Inst.getOperand(2).getImm();
4748 unsigned widthm1 = Inst.getOperand(3).getImm();
4749 if (widthm1 >= 32 - lsb)
4750 return Error(Operands[5]->getStartLoc(),
4751 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004752 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004753 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004754 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004755 // If we're parsing Thumb2, the .w variant is available and handles
4756 // most cases that are normally illegal for a Thumb1 LDM
4757 // instruction. We'll make the transformation in processInstruction()
4758 // if necessary.
4759 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004760 // Thumb LDM instructions are writeback iff the base register is not
4761 // in the register list.
4762 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004763 bool hasWritebackToken =
4764 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4765 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004766 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004767 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004768 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4769 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004770 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004771 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004772 return Error(Operands[2]->getStartLoc(),
4773 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004774 // If we should not have writeback, there must not be a '!'. This is
4775 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004776 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004777 return Error(Operands[3]->getStartLoc(),
4778 "writeback operator '!' not allowed when base register "
4779 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004780
4781 break;
4782 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004783 case ARM::t2LDMIA_UPD: {
4784 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4785 return Error(Operands[4]->getStartLoc(),
4786 "writeback operator '!' not allowed when base register "
4787 "in register list");
4788 break;
4789 }
Jim Grosbach54026372011-11-10 23:17:11 +00004790 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4791 // so only issue a diagnostic for thumb1. The instructions will be
4792 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004793 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004794 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004795 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4796 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004797 return Error(Operands[2]->getStartLoc(),
4798 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004799 break;
4800 }
4801 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004802 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004803 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4804 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004805 return Error(Operands[2]->getStartLoc(),
4806 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004807 break;
4808 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004809 case ARM::tSTMIA_UPD: {
4810 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004811 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004812 return Error(Operands[4]->getStartLoc(),
4813 "registers must be in range r0-r7");
4814 break;
4815 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004816 }
4817
4818 return false;
4819}
4820
Jim Grosbach84defb52011-12-02 22:34:51 +00004821static unsigned getRealVSTLNOpcode(unsigned Opc) {
4822 switch(Opc) {
4823 default: assert(0 && "unexpected opcode!");
4824 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4825 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4826 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4827 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4828 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4829 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4830 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4831 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4832 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4833 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4834 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4835 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4836 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4837 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4838 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4839 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4840 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4841 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4842 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4843 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4844 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4845 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4846 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4847 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4848 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4849 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4850 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4851 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4852 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4853 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4854 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4855 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4856 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4857 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4858 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4859 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4860 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4861 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4862 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4863 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4864 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4865 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4866 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4867 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4868 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4869 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4870 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4871 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4872 }
4873}
4874
4875static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004876 switch(Opc) {
4877 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00004878 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4879 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4880 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4881 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4882 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4883 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4884 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4885 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
4886 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
4887 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
4888 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
4889 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
4890 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
4891 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
4892 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
4893 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
4894 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
4895 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
4896 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
4897 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
4898 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
4899 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
4900 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
4901 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
4902 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
4903 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
4904 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
4905 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
4906 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
4907 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
4908 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
4909 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004910 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4911 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4912 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4913 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4914 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00004915 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4916 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4917 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4918 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4919 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004920 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4921 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4922 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4923 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4924 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4925 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004926 }
4927}
4928
Jim Grosbach83ec8772011-11-10 23:42:14 +00004929bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004930processInstruction(MCInst &Inst,
4931 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4932 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00004933 // Handle NEON VST1 complex aliases.
4934 case ARM::VST1LNdWB_register_Asm_8:
4935 case ARM::VST1LNdWB_register_Asm_P8:
4936 case ARM::VST1LNdWB_register_Asm_I8:
4937 case ARM::VST1LNdWB_register_Asm_S8:
4938 case ARM::VST1LNdWB_register_Asm_U8:
4939 case ARM::VST1LNdWB_register_Asm_16:
4940 case ARM::VST1LNdWB_register_Asm_P16:
4941 case ARM::VST1LNdWB_register_Asm_I16:
4942 case ARM::VST1LNdWB_register_Asm_S16:
4943 case ARM::VST1LNdWB_register_Asm_U16:
4944 case ARM::VST1LNdWB_register_Asm_32:
4945 case ARM::VST1LNdWB_register_Asm_F:
4946 case ARM::VST1LNdWB_register_Asm_F32:
4947 case ARM::VST1LNdWB_register_Asm_I32:
4948 case ARM::VST1LNdWB_register_Asm_S32:
4949 case ARM::VST1LNdWB_register_Asm_U32: {
4950 MCInst TmpInst;
4951 // Shuffle the operands around so the lane index operand is in the
4952 // right place.
4953 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4954 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4955 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4956 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4957 TmpInst.addOperand(Inst.getOperand(4)); // Rm
4958 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4959 TmpInst.addOperand(Inst.getOperand(1)); // lane
4960 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
4961 TmpInst.addOperand(Inst.getOperand(6));
4962 Inst = TmpInst;
4963 return true;
4964 }
4965 case ARM::VST1LNdWB_fixed_Asm_8:
4966 case ARM::VST1LNdWB_fixed_Asm_P8:
4967 case ARM::VST1LNdWB_fixed_Asm_I8:
4968 case ARM::VST1LNdWB_fixed_Asm_S8:
4969 case ARM::VST1LNdWB_fixed_Asm_U8:
4970 case ARM::VST1LNdWB_fixed_Asm_16:
4971 case ARM::VST1LNdWB_fixed_Asm_P16:
4972 case ARM::VST1LNdWB_fixed_Asm_I16:
4973 case ARM::VST1LNdWB_fixed_Asm_S16:
4974 case ARM::VST1LNdWB_fixed_Asm_U16:
4975 case ARM::VST1LNdWB_fixed_Asm_32:
4976 case ARM::VST1LNdWB_fixed_Asm_F:
4977 case ARM::VST1LNdWB_fixed_Asm_F32:
4978 case ARM::VST1LNdWB_fixed_Asm_I32:
4979 case ARM::VST1LNdWB_fixed_Asm_S32:
4980 case ARM::VST1LNdWB_fixed_Asm_U32: {
4981 MCInst TmpInst;
4982 // Shuffle the operands around so the lane index operand is in the
4983 // right place.
4984 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4985 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4986 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4987 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4988 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
4989 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4990 TmpInst.addOperand(Inst.getOperand(1)); // lane
4991 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
4992 TmpInst.addOperand(Inst.getOperand(5));
4993 Inst = TmpInst;
4994 return true;
4995 }
4996 case ARM::VST1LNdAsm_8:
4997 case ARM::VST1LNdAsm_P8:
4998 case ARM::VST1LNdAsm_I8:
4999 case ARM::VST1LNdAsm_S8:
5000 case ARM::VST1LNdAsm_U8:
5001 case ARM::VST1LNdAsm_16:
5002 case ARM::VST1LNdAsm_P16:
5003 case ARM::VST1LNdAsm_I16:
5004 case ARM::VST1LNdAsm_S16:
5005 case ARM::VST1LNdAsm_U16:
5006 case ARM::VST1LNdAsm_32:
5007 case ARM::VST1LNdAsm_F:
5008 case ARM::VST1LNdAsm_F32:
5009 case ARM::VST1LNdAsm_I32:
5010 case ARM::VST1LNdAsm_S32:
5011 case ARM::VST1LNdAsm_U32: {
5012 MCInst TmpInst;
5013 // Shuffle the operands around so the lane index operand is in the
5014 // right place.
5015 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5016 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5017 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5018 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5019 TmpInst.addOperand(Inst.getOperand(1)); // lane
5020 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5021 TmpInst.addOperand(Inst.getOperand(5));
5022 Inst = TmpInst;
5023 return true;
5024 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005025 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005026 case ARM::VLD1LNdWB_register_Asm_8:
5027 case ARM::VLD1LNdWB_register_Asm_P8:
5028 case ARM::VLD1LNdWB_register_Asm_I8:
5029 case ARM::VLD1LNdWB_register_Asm_S8:
5030 case ARM::VLD1LNdWB_register_Asm_U8:
5031 case ARM::VLD1LNdWB_register_Asm_16:
5032 case ARM::VLD1LNdWB_register_Asm_P16:
5033 case ARM::VLD1LNdWB_register_Asm_I16:
5034 case ARM::VLD1LNdWB_register_Asm_S16:
5035 case ARM::VLD1LNdWB_register_Asm_U16:
5036 case ARM::VLD1LNdWB_register_Asm_32:
5037 case ARM::VLD1LNdWB_register_Asm_F:
5038 case ARM::VLD1LNdWB_register_Asm_F32:
5039 case ARM::VLD1LNdWB_register_Asm_I32:
5040 case ARM::VLD1LNdWB_register_Asm_S32:
5041 case ARM::VLD1LNdWB_register_Asm_U32: {
5042 MCInst TmpInst;
5043 // Shuffle the operands around so the lane index operand is in the
5044 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005045 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005046 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5047 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5048 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5049 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5050 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5051 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5052 TmpInst.addOperand(Inst.getOperand(1)); // lane
5053 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5054 TmpInst.addOperand(Inst.getOperand(6));
5055 Inst = TmpInst;
5056 return true;
5057 }
5058 case ARM::VLD1LNdWB_fixed_Asm_8:
5059 case ARM::VLD1LNdWB_fixed_Asm_P8:
5060 case ARM::VLD1LNdWB_fixed_Asm_I8:
5061 case ARM::VLD1LNdWB_fixed_Asm_S8:
5062 case ARM::VLD1LNdWB_fixed_Asm_U8:
5063 case ARM::VLD1LNdWB_fixed_Asm_16:
5064 case ARM::VLD1LNdWB_fixed_Asm_P16:
5065 case ARM::VLD1LNdWB_fixed_Asm_I16:
5066 case ARM::VLD1LNdWB_fixed_Asm_S16:
5067 case ARM::VLD1LNdWB_fixed_Asm_U16:
5068 case ARM::VLD1LNdWB_fixed_Asm_32:
5069 case ARM::VLD1LNdWB_fixed_Asm_F:
5070 case ARM::VLD1LNdWB_fixed_Asm_F32:
5071 case ARM::VLD1LNdWB_fixed_Asm_I32:
5072 case ARM::VLD1LNdWB_fixed_Asm_S32:
5073 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5074 MCInst TmpInst;
5075 // Shuffle the operands around so the lane index operand is in the
5076 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005077 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005078 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5079 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5080 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5081 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5082 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5083 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5084 TmpInst.addOperand(Inst.getOperand(1)); // lane
5085 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5086 TmpInst.addOperand(Inst.getOperand(5));
5087 Inst = TmpInst;
5088 return true;
5089 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005090 case ARM::VLD1LNdAsm_8:
5091 case ARM::VLD1LNdAsm_P8:
5092 case ARM::VLD1LNdAsm_I8:
5093 case ARM::VLD1LNdAsm_S8:
5094 case ARM::VLD1LNdAsm_U8:
5095 case ARM::VLD1LNdAsm_16:
5096 case ARM::VLD1LNdAsm_P16:
5097 case ARM::VLD1LNdAsm_I16:
5098 case ARM::VLD1LNdAsm_S16:
5099 case ARM::VLD1LNdAsm_U16:
5100 case ARM::VLD1LNdAsm_32:
5101 case ARM::VLD1LNdAsm_F:
5102 case ARM::VLD1LNdAsm_F32:
5103 case ARM::VLD1LNdAsm_I32:
5104 case ARM::VLD1LNdAsm_S32:
5105 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005106 MCInst TmpInst;
5107 // Shuffle the operands around so the lane index operand is in the
5108 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005109 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005110 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5111 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5112 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5113 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5114 TmpInst.addOperand(Inst.getOperand(1)); // lane
5115 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5116 TmpInst.addOperand(Inst.getOperand(5));
5117 Inst = TmpInst;
5118 return true;
5119 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00005120 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005121 case ARM::ASRr:
5122 case ARM::LSRr:
5123 case ARM::LSLr:
5124 case ARM::RORr: {
5125 ARM_AM::ShiftOpc ShiftTy;
5126 switch(Inst.getOpcode()) {
5127 default: llvm_unreachable("unexpected opcode!");
5128 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5129 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5130 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5131 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5132 }
5133 // A shift by zero is a plain MOVr, not a MOVsi.
5134 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5135 MCInst TmpInst;
5136 TmpInst.setOpcode(ARM::MOVsr);
5137 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5138 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5139 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5140 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5141 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5142 TmpInst.addOperand(Inst.getOperand(4));
5143 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5144 Inst = TmpInst;
5145 return true;
5146 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005147 case ARM::ASRi:
5148 case ARM::LSRi:
5149 case ARM::LSLi:
5150 case ARM::RORi: {
5151 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005152 switch(Inst.getOpcode()) {
5153 default: llvm_unreachable("unexpected opcode!");
5154 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5155 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5156 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5157 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5158 }
5159 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005160 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005161 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5162 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005163 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005164 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005165 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5166 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005167 if (Opc == ARM::MOVsi)
5168 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005169 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5170 TmpInst.addOperand(Inst.getOperand(4));
5171 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5172 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005173 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005174 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005175 case ARM::RRXi: {
5176 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5177 MCInst TmpInst;
5178 TmpInst.setOpcode(ARM::MOVsi);
5179 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5180 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5181 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5182 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5183 TmpInst.addOperand(Inst.getOperand(3));
5184 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5185 Inst = TmpInst;
5186 return true;
5187 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005188 case ARM::t2LDMIA_UPD: {
5189 // If this is a load of a single register, then we should use
5190 // a post-indexed LDR instruction instead, per the ARM ARM.
5191 if (Inst.getNumOperands() != 5)
5192 return false;
5193 MCInst TmpInst;
5194 TmpInst.setOpcode(ARM::t2LDR_POST);
5195 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5196 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5197 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5198 TmpInst.addOperand(MCOperand::CreateImm(4));
5199 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5200 TmpInst.addOperand(Inst.getOperand(3));
5201 Inst = TmpInst;
5202 return true;
5203 }
5204 case ARM::t2STMDB_UPD: {
5205 // If this is a store of a single register, then we should use
5206 // a pre-indexed STR instruction instead, per the ARM ARM.
5207 if (Inst.getNumOperands() != 5)
5208 return false;
5209 MCInst TmpInst;
5210 TmpInst.setOpcode(ARM::t2STR_PRE);
5211 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5212 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5213 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5214 TmpInst.addOperand(MCOperand::CreateImm(-4));
5215 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5216 TmpInst.addOperand(Inst.getOperand(3));
5217 Inst = TmpInst;
5218 return true;
5219 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005220 case ARM::LDMIA_UPD:
5221 // If this is a load of a single register via a 'pop', then we should use
5222 // a post-indexed LDR instruction instead, per the ARM ARM.
5223 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5224 Inst.getNumOperands() == 5) {
5225 MCInst TmpInst;
5226 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5227 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5228 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5229 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5230 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5231 TmpInst.addOperand(MCOperand::CreateImm(4));
5232 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5233 TmpInst.addOperand(Inst.getOperand(3));
5234 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005235 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005236 }
5237 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005238 case ARM::STMDB_UPD:
5239 // If this is a store of a single register via a 'push', then we should use
5240 // a pre-indexed STR instruction instead, per the ARM ARM.
5241 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5242 Inst.getNumOperands() == 5) {
5243 MCInst TmpInst;
5244 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5245 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5246 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5247 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5248 TmpInst.addOperand(MCOperand::CreateImm(-4));
5249 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5250 TmpInst.addOperand(Inst.getOperand(3));
5251 Inst = TmpInst;
5252 }
5253 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005254 case ARM::t2ADDri12:
5255 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5256 // mnemonic was used (not "addw"), encoding T3 is preferred.
5257 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5258 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5259 break;
5260 Inst.setOpcode(ARM::t2ADDri);
5261 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5262 break;
5263 case ARM::t2SUBri12:
5264 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5265 // mnemonic was used (not "subw"), encoding T3 is preferred.
5266 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5267 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5268 break;
5269 Inst.setOpcode(ARM::t2SUBri);
5270 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5271 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005272 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005273 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5274 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5275 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5276 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005277 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005278 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005279 return true;
5280 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005281 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005282 case ARM::tSUBi8:
5283 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5284 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5285 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5286 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005287 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005288 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005289 return true;
5290 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005291 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005292 case ARM::t2ADDrr: {
5293 // If the destination and first source operand are the same, and
5294 // there's no setting of the flags, use encoding T2 instead of T3.
5295 // Note that this is only for ADD, not SUB. This mirrors the system
5296 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5297 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5298 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005299 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5300 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005301 break;
5302 MCInst TmpInst;
5303 TmpInst.setOpcode(ARM::tADDhirr);
5304 TmpInst.addOperand(Inst.getOperand(0));
5305 TmpInst.addOperand(Inst.getOperand(0));
5306 TmpInst.addOperand(Inst.getOperand(2));
5307 TmpInst.addOperand(Inst.getOperand(3));
5308 TmpInst.addOperand(Inst.getOperand(4));
5309 Inst = TmpInst;
5310 return true;
5311 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005312 case ARM::tB:
5313 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005314 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005315 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005316 return true;
5317 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005318 break;
5319 case ARM::t2B:
5320 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005321 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005322 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005323 return true;
5324 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005325 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005326 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005327 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005328 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005329 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005330 return true;
5331 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005332 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005333 case ARM::tBcc:
5334 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005335 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005336 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005337 return true;
5338 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005339 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005340 case ARM::tLDMIA: {
5341 // If the register list contains any high registers, or if the writeback
5342 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5343 // instead if we're in Thumb2. Otherwise, this should have generated
5344 // an error in validateInstruction().
5345 unsigned Rn = Inst.getOperand(0).getReg();
5346 bool hasWritebackToken =
5347 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5348 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5349 bool listContainsBase;
5350 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5351 (!listContainsBase && !hasWritebackToken) ||
5352 (listContainsBase && hasWritebackToken)) {
5353 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5354 assert (isThumbTwo());
5355 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5356 // If we're switching to the updating version, we need to insert
5357 // the writeback tied operand.
5358 if (hasWritebackToken)
5359 Inst.insert(Inst.begin(),
5360 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005361 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005362 }
5363 break;
5364 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005365 case ARM::tSTMIA_UPD: {
5366 // If the register list contains any high registers, we need to use
5367 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5368 // should have generated an error in validateInstruction().
5369 unsigned Rn = Inst.getOperand(0).getReg();
5370 bool listContainsBase;
5371 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5372 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5373 assert (isThumbTwo());
5374 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005375 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005376 }
5377 break;
5378 }
Jim Grosbach54026372011-11-10 23:17:11 +00005379 case ARM::tPOP: {
5380 bool listContainsBase;
5381 // If the register list contains any high registers, we need to use
5382 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5383 // should have generated an error in validateInstruction().
5384 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005385 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005386 assert (isThumbTwo());
5387 Inst.setOpcode(ARM::t2LDMIA_UPD);
5388 // Add the base register and writeback operands.
5389 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5390 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005391 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005392 }
5393 case ARM::tPUSH: {
5394 bool listContainsBase;
5395 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005396 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005397 assert (isThumbTwo());
5398 Inst.setOpcode(ARM::t2STMDB_UPD);
5399 // Add the base register and writeback operands.
5400 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5401 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005402 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005403 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005404 case ARM::t2MOVi: {
5405 // If we can use the 16-bit encoding and the user didn't explicitly
5406 // request the 32-bit variant, transform it here.
5407 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5408 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005409 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5410 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5411 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005412 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5413 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5414 // The operands aren't in the same order for tMOVi8...
5415 MCInst TmpInst;
5416 TmpInst.setOpcode(ARM::tMOVi8);
5417 TmpInst.addOperand(Inst.getOperand(0));
5418 TmpInst.addOperand(Inst.getOperand(4));
5419 TmpInst.addOperand(Inst.getOperand(1));
5420 TmpInst.addOperand(Inst.getOperand(2));
5421 TmpInst.addOperand(Inst.getOperand(3));
5422 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005423 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005424 }
5425 break;
5426 }
5427 case ARM::t2MOVr: {
5428 // If we can use the 16-bit encoding and the user didn't explicitly
5429 // request the 32-bit variant, transform it here.
5430 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5431 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5432 Inst.getOperand(2).getImm() == ARMCC::AL &&
5433 Inst.getOperand(4).getReg() == ARM::CPSR &&
5434 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5435 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5436 // The operands aren't the same for tMOV[S]r... (no cc_out)
5437 MCInst TmpInst;
5438 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5439 TmpInst.addOperand(Inst.getOperand(0));
5440 TmpInst.addOperand(Inst.getOperand(1));
5441 TmpInst.addOperand(Inst.getOperand(2));
5442 TmpInst.addOperand(Inst.getOperand(3));
5443 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005444 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005445 }
5446 break;
5447 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005448 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005449 case ARM::t2SXTB:
5450 case ARM::t2UXTH:
5451 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005452 // If we can use the 16-bit encoding and the user didn't explicitly
5453 // request the 32-bit variant, transform it here.
5454 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5455 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5456 Inst.getOperand(2).getImm() == 0 &&
5457 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5458 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005459 unsigned NewOpc;
5460 switch (Inst.getOpcode()) {
5461 default: llvm_unreachable("Illegal opcode!");
5462 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5463 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5464 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5465 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5466 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005467 // The operands aren't the same for thumb1 (no rotate operand).
5468 MCInst TmpInst;
5469 TmpInst.setOpcode(NewOpc);
5470 TmpInst.addOperand(Inst.getOperand(0));
5471 TmpInst.addOperand(Inst.getOperand(1));
5472 TmpInst.addOperand(Inst.getOperand(3));
5473 TmpInst.addOperand(Inst.getOperand(4));
5474 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005475 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005476 }
5477 break;
5478 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005479 case ARM::t2IT: {
5480 // The mask bits for all but the first condition are represented as
5481 // the low bit of the condition code value implies 't'. We currently
5482 // always have 1 implies 't', so XOR toggle the bits if the low bit
5483 // of the condition code is zero. The encoding also expects the low
5484 // bit of the condition to be encoded as bit 4 of the mask operand,
5485 // so mask that in if needed
5486 MCOperand &MO = Inst.getOperand(1);
5487 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005488 unsigned OrigMask = Mask;
5489 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005490 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005491 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5492 for (unsigned i = 3; i != TZ; --i)
5493 Mask ^= 1 << i;
5494 } else
5495 Mask |= 0x10;
5496 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005497
5498 // Set up the IT block state according to the IT instruction we just
5499 // matched.
5500 assert(!inITBlock() && "nested IT blocks?!");
5501 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5502 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5503 ITState.CurPosition = 0;
5504 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005505 break;
5506 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005507 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005508 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005509}
5510
Jim Grosbach47a0d522011-08-16 20:45:50 +00005511unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5512 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5513 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005514 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005515 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005516 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5517 assert(MCID.hasOptionalDef() &&
5518 "optionally flag setting instruction missing optional def operand");
5519 assert(MCID.NumOperands == Inst.getNumOperands() &&
5520 "operand count mismatch!");
5521 // Find the optional-def operand (cc_out).
5522 unsigned OpNo;
5523 for (OpNo = 0;
5524 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5525 ++OpNo)
5526 ;
5527 // If we're parsing Thumb1, reject it completely.
5528 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5529 return Match_MnemonicFail;
5530 // If we're parsing Thumb2, which form is legal depends on whether we're
5531 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005532 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5533 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005534 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005535 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5536 inITBlock())
5537 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005538 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005539 // Some high-register supporting Thumb1 encodings only allow both registers
5540 // to be from r0-r7 when in Thumb2.
5541 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5542 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5543 isARMLowRegister(Inst.getOperand(2).getReg()))
5544 return Match_RequiresThumb2;
5545 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005546 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005547 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5548 isARMLowRegister(Inst.getOperand(1).getReg()))
5549 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005550 return Match_Success;
5551}
5552
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005553bool ARMAsmParser::
5554MatchAndEmitInstruction(SMLoc IDLoc,
5555 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5556 MCStreamer &Out) {
5557 MCInst Inst;
5558 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005559 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005560 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005561 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005562 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005563 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005564 // Context sensitive operand constraints aren't handled by the matcher,
5565 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005566 if (validateInstruction(Inst, Operands)) {
5567 // Still progress the IT block, otherwise one wrong condition causes
5568 // nasty cascading errors.
5569 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005570 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005571 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005572
Jim Grosbachf8fce712011-08-11 17:35:48 +00005573 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005574 // encoding is selected. Loop on it while changes happen so the
5575 // individual transformations can chain off each other. E.g.,
5576 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5577 while (processInstruction(Inst, Operands))
5578 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005579
Jim Grosbacha1109882011-09-02 23:22:08 +00005580 // Only move forward at the very end so that everything in validate
5581 // and process gets a consistent answer about whether we're in an IT
5582 // block.
5583 forwardITPosition();
5584
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005585 Out.EmitInstruction(Inst);
5586 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005587 case Match_MissingFeature:
5588 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5589 return true;
5590 case Match_InvalidOperand: {
5591 SMLoc ErrorLoc = IDLoc;
5592 if (ErrorInfo != ~0U) {
5593 if (ErrorInfo >= Operands.size())
5594 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005595
Chris Lattnere73d4f82010-10-28 21:41:58 +00005596 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5597 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5598 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005599
Chris Lattnere73d4f82010-10-28 21:41:58 +00005600 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005601 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005602 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005603 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005604 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005605 // The converter function will have already emited a diagnostic.
5606 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005607 case Match_RequiresNotITBlock:
5608 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005609 case Match_RequiresITBlock:
5610 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005611 case Match_RequiresV6:
5612 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5613 case Match_RequiresThumb2:
5614 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005615 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005616
Eric Christopherc223e2b2010-10-29 09:26:59 +00005617 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005618 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005619}
5620
Jim Grosbach1355cf12011-07-26 17:10:22 +00005621/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005622bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5623 StringRef IDVal = DirectiveID.getIdentifier();
5624 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005625 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005626 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005627 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005628 else if (IDVal == ".arm")
5629 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005630 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005631 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005632 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005633 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005634 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005635 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005636 return true;
5637}
5638
Jim Grosbach1355cf12011-07-26 17:10:22 +00005639/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005640/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005641bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005642 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5643 for (;;) {
5644 const MCExpr *Value;
5645 if (getParser().ParseExpression(Value))
5646 return true;
5647
Chris Lattneraaec2052010-01-19 19:46:13 +00005648 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005649
5650 if (getLexer().is(AsmToken::EndOfStatement))
5651 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005652
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005653 // FIXME: Improve diagnostic.
5654 if (getLexer().isNot(AsmToken::Comma))
5655 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005656 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005657 }
5658 }
5659
Sean Callananb9a25b72010-01-19 20:27:46 +00005660 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005661 return false;
5662}
5663
Jim Grosbach1355cf12011-07-26 17:10:22 +00005664/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005665/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005666bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005667 if (getLexer().isNot(AsmToken::EndOfStatement))
5668 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005669 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005670
Jim Grosbach9a70df92011-12-07 18:04:19 +00005671 if (!isThumb())
5672 SwitchMode();
5673 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5674 return false;
5675}
5676
5677/// parseDirectiveARM
5678/// ::= .arm
5679bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5680 if (getLexer().isNot(AsmToken::EndOfStatement))
5681 return Error(L, "unexpected token in directive");
5682 Parser.Lex();
5683
5684 if (isThumb())
5685 SwitchMode();
5686 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005687 return false;
5688}
5689
Jim Grosbach1355cf12011-07-26 17:10:22 +00005690/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005691/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005692bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005693 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5694 bool isMachO = MAI.hasSubsectionsViaSymbols();
5695 StringRef Name;
5696
5697 // Darwin asm has function name after .thumb_func direction
5698 // ELF doesn't
5699 if (isMachO) {
5700 const AsmToken &Tok = Parser.getTok();
5701 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5702 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005703 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005704 Parser.Lex(); // Consume the identifier token.
5705 }
5706
Jim Grosbachd475f862011-11-10 20:48:53 +00005707 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005708 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005709 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005710
Rafael Espindola64695402011-05-16 16:17:21 +00005711 // FIXME: assuming function name will be the line following .thumb_func
5712 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005713 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005714 }
5715
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005716 // Mark symbol as a thumb symbol.
5717 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5718 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005719 return false;
5720}
5721
Jim Grosbach1355cf12011-07-26 17:10:22 +00005722/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005723/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005724bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005725 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005726 if (Tok.isNot(AsmToken::Identifier))
5727 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005728 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005729 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005730 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005731 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005732 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005733 else
5734 return Error(L, "unrecognized syntax mode in .syntax directive");
5735
5736 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005737 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005738 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005739
5740 // TODO tell the MC streamer the mode
5741 // getParser().getStreamer().Emit???();
5742 return false;
5743}
5744
Jim Grosbach1355cf12011-07-26 17:10:22 +00005745/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005746/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005747bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005748 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005749 if (Tok.isNot(AsmToken::Integer))
5750 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005751 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005752 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005753 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005754 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005755 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005756 else
5757 return Error(L, "invalid operand to .code directive");
5758
5759 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005760 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005761 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005762
Evan Cheng32869202011-07-08 22:36:29 +00005763 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005764 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005765 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005766 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005767 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005768 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005769 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005770 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005771 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005772
Kevin Enderby515d5092009-10-15 20:48:48 +00005773 return false;
5774}
5775
Sean Callanan90b70972010-04-07 20:29:34 +00005776extern "C" void LLVMInitializeARMAsmLexer();
5777
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005778/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005779extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005780 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5781 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005782 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005783}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005784
Chris Lattner0692ee62010-09-06 19:11:01 +00005785#define GET_REGISTER_MATCHER
5786#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005787#include "ARMGenAsmMatcher.inc"