blob: 56f9955cf536d9c6ccfad624564fce17bf45dd21 [file] [log] [blame]
Kevin Enderbyccab3172009-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 Cheng11424442011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chenga20cde32011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattner00646cf2010-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 Espindolae90c1cb2011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbachc6db8ce2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyccab3172009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng4d6c9d72011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng11424442011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng11424442011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach3d1eac82011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng2bb40352011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbar4a863e62010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach5c932b22011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramerdebe69f2011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng11424442011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Andersona098d152011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000036
Kevin Enderbyccab3172009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000039namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000042
Evan Cheng11424442011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbached16ec42011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbached16ec42011-08-29 22:24:09 +000075
76
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000097
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000103
Evan Cheng4d1ca962011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000110 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloy21efa7d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng284b4672011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000123 }
James Molloy21efa7d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000127
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000130
Chris Lattner3e4582a2010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000147 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
148 StringRef Op, int Low, int High);
149 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
150 return parsePKHImm(O, "lsl", 0, 31);
151 }
152 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "asr", 1, 32);
154 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000161 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000162
163 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000164 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
165 const SmallVectorImpl<MCParsedAsmOperand*> &);
166 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000168 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000170 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000172 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000174 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000176 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000178 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000180 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000182 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
184 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000190 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000192 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000194 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000196 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000198
199 bool validateInstruction(MCInst &Inst,
200 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000201 void processInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000203 bool shouldOmitCCOutOperand(StringRef Mnemonic,
204 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000205
Kevin Enderbyccab3172009-09-15 00:27:25 +0000206public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000207 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000208 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000209 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000210 Match_RequiresV6,
211 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000212 };
213
Evan Cheng91111d22011-07-09 05:47:46 +0000214 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000215 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000216 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000217
Evan Cheng4d1ca962011-07-08 01:53:10 +0000218 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000219 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000220
221 // Not in an ITBlock to start with.
222 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000223 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000224
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000225 // Implementation of the MCTargetAsmParser interface:
226 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
227 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000228 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000229 bool ParseDirective(AsmToken DirectiveID);
230
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000231 unsigned checkTargetMatchPredicate(MCInst &Inst);
232
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000233 bool MatchAndEmitInstruction(SMLoc IDLoc,
234 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
235 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000236};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000237} // end anonymous namespace
238
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000239namespace {
240
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000241/// ARMOperand - Instances of this class represent a parsed ARM machine
242/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000243class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000244 enum KindTy {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000245 CondCode,
Jim Grosbach0bfb4d52010-12-06 18:21:12 +0000246 CCOut,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000247 ITCondMask,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000248 CoprocNum,
249 CoprocReg,
Kevin Enderbyf5079942009-10-13 22:19:02 +0000250 Immediate,
Jim Grosbache7fbce72011-10-03 23:38:36 +0000251 FPImmediate,
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000252 MemBarrierOpt,
Daniel Dunbard8042b72010-08-11 06:36:53 +0000253 Memory,
Jim Grosbachd3595712011-08-03 23:50:40 +0000254 PostIndexRegister,
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000255 MSRMask,
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000256 ProcIFlags,
Daniel Dunbard8042b72010-08-11 06:36:53 +0000257 Register,
Bill Wendling7cef4472010-11-06 19:56:04 +0000258 RegisterList,
Bill Wendling9898ac92010-11-17 04:32:08 +0000259 DPRRegisterList,
260 SPRRegisterList,
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000261 ShiftedRegister,
Owen Andersonb595ed02011-07-21 18:54:16 +0000262 ShiftedImmediate,
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000263 ShifterImmediate,
Jim Grosbach833b9d32011-07-27 20:15:40 +0000264 RotateImmediate,
Jim Grosbach864b6092011-07-28 21:34:26 +0000265 BitfieldDescriptor,
Daniel Dunbard8042b72010-08-11 06:36:53 +0000266 Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000267 } Kind;
268
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000269 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000270 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000271
272 union {
273 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000274 ARMCC::CondCodes Val;
275 } CC;
276
277 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000278 unsigned Val;
279 } Cop;
280
281 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000282 unsigned Mask:4;
283 } ITMask;
284
285 struct {
286 ARM_MB::MemBOpt Val;
287 } MBOpt;
288
289 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000290 ARM_PROC::IFlags Val;
291 } IFlags;
292
293 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000294 unsigned Val;
295 } MMask;
296
297 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000298 const char *Data;
299 unsigned Length;
300 } Tok;
301
302 struct {
303 unsigned RegNum;
304 } Reg;
305
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000306 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000307 const MCExpr *Val;
308 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000309
Jim Grosbache7fbce72011-10-03 23:38:36 +0000310 struct {
311 unsigned Val; // encoded 8-bit representation
312 } FPImm;
313
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000314 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000315 struct {
316 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000317 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
318 // was specified.
319 const MCConstantExpr *OffsetImm; // Offset immediate value
320 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
321 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach3d0b3a32011-08-05 22:03:36 +0000322 unsigned ShiftImm; // shift for OffsetReg.
Jim Grosbachd3595712011-08-03 23:50:40 +0000323 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000324 } Mem;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000325
326 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000327 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000328 bool isAdd;
329 ARM_AM::ShiftOpc ShiftTy;
330 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000331 } PostIdxReg;
332
333 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000334 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000335 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000336 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000337 struct {
338 ARM_AM::ShiftOpc ShiftTy;
339 unsigned SrcReg;
340 unsigned ShiftReg;
341 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000342 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000343 struct {
344 ARM_AM::ShiftOpc ShiftTy;
345 unsigned SrcReg;
346 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000347 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000348 struct {
349 unsigned Imm;
350 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000351 struct {
352 unsigned LSB;
353 unsigned Width;
354 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000355 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000356
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000357 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
358public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000359 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
360 Kind = o.Kind;
361 StartLoc = o.StartLoc;
362 EndLoc = o.EndLoc;
363 switch (Kind) {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000364 case CondCode:
365 CC = o.CC;
366 break;
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000367 case ITCondMask:
368 ITMask = o.ITMask;
369 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000370 case Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000371 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000372 break;
Jim Grosbach0bfb4d52010-12-06 18:21:12 +0000373 case CCOut:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000374 case Register:
375 Reg = o.Reg;
376 break;
Bill Wendling7cef4472010-11-06 19:56:04 +0000377 case RegisterList:
Bill Wendling9898ac92010-11-17 04:32:08 +0000378 case DPRRegisterList:
379 case SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000380 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000381 break;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000382 case CoprocNum:
383 case CoprocReg:
384 Cop = o.Cop;
385 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000386 case Immediate:
387 Imm = o.Imm;
388 break;
Jim Grosbache7fbce72011-10-03 23:38:36 +0000389 case FPImmediate:
390 FPImm = o.FPImm;
391 break;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000392 case MemBarrierOpt:
393 MBOpt = o.MBOpt;
394 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000395 case Memory:
396 Mem = o.Mem;
397 break;
Jim Grosbachd3595712011-08-03 23:50:40 +0000398 case PostIndexRegister:
399 PostIdxReg = o.PostIdxReg;
400 break;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000401 case MSRMask:
402 MMask = o.MMask;
403 break;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000404 case ProcIFlags:
405 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000406 break;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000407 case ShifterImmediate:
408 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000409 break;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000410 case ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000411 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000412 break;
Owen Andersonb595ed02011-07-21 18:54:16 +0000413 case ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000414 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000415 break;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000416 case RotateImmediate:
417 RotImm = o.RotImm;
418 break;
Jim Grosbach864b6092011-07-28 21:34:26 +0000419 case BitfieldDescriptor:
420 Bitfield = o.Bitfield;
421 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000422 }
423 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000424
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000425 /// getStartLoc - Get the location of the first token of this operand.
426 SMLoc getStartLoc() const { return StartLoc; }
427 /// getEndLoc - Get the location of the last token of this operand.
428 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000429
Daniel Dunbard8042b72010-08-11 06:36:53 +0000430 ARMCC::CondCodes getCondCode() const {
431 assert(Kind == CondCode && "Invalid access!");
432 return CC.Val;
433 }
434
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000435 unsigned getCoproc() const {
436 assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
437 return Cop.Val;
438 }
439
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000440 StringRef getToken() const {
441 assert(Kind == Token && "Invalid access!");
442 return StringRef(Tok.Data, Tok.Length);
443 }
444
445 unsigned getReg() const {
Benjamin Kramercfa9a892010-12-07 15:50:35 +0000446 assert((Kind == Register || Kind == CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000447 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000448 }
449
Bill Wendlingbed94652010-11-09 23:28:44 +0000450 const SmallVectorImpl<unsigned> &getRegList() const {
Bill Wendling9898ac92010-11-17 04:32:08 +0000451 assert((Kind == RegisterList || Kind == DPRRegisterList ||
452 Kind == SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000453 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000454 }
455
Kevin Enderbyf5079942009-10-13 22:19:02 +0000456 const MCExpr *getImm() const {
457 assert(Kind == Immediate && "Invalid access!");
458 return Imm.Val;
459 }
460
Jim Grosbache7fbce72011-10-03 23:38:36 +0000461 unsigned getFPImm() const {
462 assert(Kind == FPImmediate && "Invalid access!");
463 return FPImm.Val;
464 }
465
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000466 ARM_MB::MemBOpt getMemBarrierOpt() const {
467 assert(Kind == MemBarrierOpt && "Invalid access!");
468 return MBOpt.Val;
469 }
470
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000471 ARM_PROC::IFlags getProcIFlags() const {
472 assert(Kind == ProcIFlags && "Invalid access!");
473 return IFlags.Val;
474 }
475
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000476 unsigned getMSRMask() const {
477 assert(Kind == MSRMask && "Invalid access!");
478 return MMask.Val;
479 }
480
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000481 bool isCoprocNum() const { return Kind == CoprocNum; }
482 bool isCoprocReg() const { return Kind == CoprocReg; }
Daniel Dunbard8042b72010-08-11 06:36:53 +0000483 bool isCondCode() const { return Kind == CondCode; }
Jim Grosbach0bfb4d52010-12-06 18:21:12 +0000484 bool isCCOut() const { return Kind == CCOut; }
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000485 bool isITMask() const { return Kind == ITCondMask; }
486 bool isITCondCode() const { return Kind == CondCode; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000487 bool isImm() const { return Kind == Immediate; }
Jim Grosbache7fbce72011-10-03 23:38:36 +0000488 bool isFPImm() const { return Kind == FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000489 bool isImm8s4() const {
490 if (Kind != Immediate)
491 return false;
492 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
493 if (!CE) return false;
494 int64_t Value = CE->getValue();
495 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
496 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000497 bool isImm0_1020s4() const {
498 if (Kind != Immediate)
499 return false;
500 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
501 if (!CE) return false;
502 int64_t Value = CE->getValue();
503 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
504 }
505 bool isImm0_508s4() const {
506 if (Kind != Immediate)
507 return false;
508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
509 if (!CE) return false;
510 int64_t Value = CE->getValue();
511 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
512 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000513 bool isImm0_255() const {
514 if (Kind != Immediate)
515 return false;
516 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
517 if (!CE) return false;
518 int64_t Value = CE->getValue();
519 return Value >= 0 && Value < 256;
520 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000521 bool isImm0_7() const {
522 if (Kind != Immediate)
523 return false;
524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
525 if (!CE) return false;
526 int64_t Value = CE->getValue();
527 return Value >= 0 && Value < 8;
528 }
529 bool isImm0_15() const {
530 if (Kind != Immediate)
531 return false;
532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
533 if (!CE) return false;
534 int64_t Value = CE->getValue();
535 return Value >= 0 && Value < 16;
536 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000537 bool isImm0_31() const {
538 if (Kind != Immediate)
539 return false;
540 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
541 if (!CE) return false;
542 int64_t Value = CE->getValue();
543 return Value >= 0 && Value < 32;
544 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000545 bool isImm1_16() const {
546 if (Kind != Immediate)
547 return false;
548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
549 if (!CE) return false;
550 int64_t Value = CE->getValue();
551 return Value > 0 && Value < 17;
552 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000553 bool isImm1_32() const {
554 if (Kind != Immediate)
555 return false;
556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
557 if (!CE) return false;
558 int64_t Value = CE->getValue();
559 return Value > 0 && Value < 33;
560 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000561 bool isImm0_65535() const {
562 if (Kind != Immediate)
563 return false;
564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
565 if (!CE) return false;
566 int64_t Value = CE->getValue();
567 return Value >= 0 && Value < 65536;
568 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000569 bool isImm0_65535Expr() const {
570 if (Kind != Immediate)
571 return false;
572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
573 // If it's not a constant expression, it'll generate a fixup and be
574 // handled later.
575 if (!CE) return true;
576 int64_t Value = CE->getValue();
577 return Value >= 0 && Value < 65536;
578 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000579 bool isImm24bit() const {
580 if (Kind != Immediate)
581 return false;
582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
583 if (!CE) return false;
584 int64_t Value = CE->getValue();
585 return Value >= 0 && Value <= 0xffffff;
586 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000587 bool isImmThumbSR() const {
588 if (Kind != Immediate)
589 return false;
590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
591 if (!CE) return false;
592 int64_t Value = CE->getValue();
593 return Value > 0 && Value < 33;
594 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000595 bool isPKHLSLImm() const {
596 if (Kind != Immediate)
597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 32;
602 }
603 bool isPKHASRImm() const {
604 if (Kind != Immediate)
605 return false;
606 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
607 if (!CE) return false;
608 int64_t Value = CE->getValue();
609 return Value > 0 && Value <= 32;
610 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000611 bool isARMSOImm() const {
612 if (Kind != Immediate)
613 return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = CE->getValue();
617 return ARM_AM::getSOImmVal(Value) != -1;
618 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000619 bool isT2SOImm() const {
620 if (Kind != Immediate)
621 return false;
622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return ARM_AM::getT2SOImmVal(Value) != -1;
626 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000627 bool isSetEndImm() const {
628 if (Kind != Immediate)
629 return false;
630 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
631 if (!CE) return false;
632 int64_t Value = CE->getValue();
633 return Value == 1 || Value == 0;
634 }
Bill Wendling2f9d17c2010-11-08 00:32:40 +0000635 bool isReg() const { return Kind == Register; }
Bill Wendling7cef4472010-11-06 19:56:04 +0000636 bool isRegList() const { return Kind == RegisterList; }
Bill Wendling9898ac92010-11-17 04:32:08 +0000637 bool isDPRRegList() const { return Kind == DPRRegisterList; }
638 bool isSPRRegList() const { return Kind == SPRRegisterList; }
Chris Lattner5d6f6a02010-10-29 00:27:31 +0000639 bool isToken() const { return Kind == Token; }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000640 bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
Chris Lattner5d6f6a02010-10-29 00:27:31 +0000641 bool isMemory() const { return Kind == Memory; }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000642 bool isShifterImm() const { return Kind == ShifterImmediate; }
Jim Grosbachac798e12011-07-25 20:49:51 +0000643 bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
644 bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
Jim Grosbach833b9d32011-07-27 20:15:40 +0000645 bool isRotImm() const { return Kind == RotateImmediate; }
Jim Grosbach864b6092011-07-28 21:34:26 +0000646 bool isBitfield() const { return Kind == BitfieldDescriptor; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000647 bool isPostIdxRegShifted() const { return Kind == PostIndexRegister; }
648 bool isPostIdxReg() const {
649 return Kind == PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
650 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000651 bool isMemNoOffset() const {
652 if (Kind != Memory)
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000653 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000654 // No offset of any kind.
655 return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0;
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000656 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000657 bool isAddrMode2() const {
658 if (Kind != Memory)
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000659 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000660 // Check for register offset.
661 if (Mem.OffsetRegNum) return true;
662 // Immediate offset in range [-4095, 4095].
663 if (!Mem.OffsetImm) return true;
664 int64_t Val = Mem.OffsetImm->getValue();
665 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000666 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000667 bool isAM2OffsetImm() const {
668 if (Kind != Immediate)
669 return false;
670 // Immediate offset in range [-4095, 4095].
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Val = CE->getValue();
674 return Val > -4096 && Val < 4096;
675 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000676 bool isAddrMode3() const {
677 if (Kind != Memory)
678 return false;
679 // No shifts are legal for AM3.
680 if (Mem.ShiftType != ARM_AM::no_shift) return false;
681 // Check for register offset.
682 if (Mem.OffsetRegNum) return true;
683 // Immediate offset in range [-255, 255].
684 if (!Mem.OffsetImm) return true;
685 int64_t Val = Mem.OffsetImm->getValue();
686 return Val > -256 && Val < 256;
687 }
688 bool isAM3Offset() const {
689 if (Kind != Immediate && Kind != PostIndexRegister)
690 return false;
691 if (Kind == PostIndexRegister)
692 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
693 // Immediate offset in range [-255, 255].
694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
695 if (!CE) return false;
696 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000697 // Special case, #-0 is INT32_MIN.
698 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000699 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000700 bool isAddrMode5() const {
701 if (Kind != Memory)
Bill Wendling8d2aa032010-11-08 23:49:57 +0000702 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000703 // Check for register offset.
704 if (Mem.OffsetRegNum) return false;
705 // Immediate offset in range [-1020, 1020] and a multiple of 4.
706 if (!Mem.OffsetImm) return true;
707 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000708 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
709 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000710 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000711 bool isMemTBB() const {
712 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
713 Mem.ShiftType != ARM_AM::no_shift)
714 return false;
715 return true;
716 }
717 bool isMemTBH() const {
718 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
719 Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm != 1)
720 return false;
721 return true;
722 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000723 bool isMemRegOffset() const {
724 if (Kind != Memory || !Mem.OffsetRegNum)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000725 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000726 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000727 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000728 bool isT2MemRegOffset() const {
729 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative)
730 return false;
731 // Only lsl #{0, 1, 2, 3} allowed.
732 if (Mem.ShiftType == ARM_AM::no_shift)
733 return true;
734 if (Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm > 3)
735 return false;
736 return true;
737 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000738 bool isMemThumbRR() const {
739 // Thumb reg+reg addressing is simple. Just two registers, a base and
740 // an offset. No shifts, negations or any other complicating factors.
741 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
742 Mem.ShiftType != ARM_AM::no_shift)
Bill Wendling811c9362010-11-30 07:44:32 +0000743 return false;
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000744 return isARMLowRegister(Mem.BaseRegNum) &&
745 (!Mem.OffsetRegNum || isARMLowRegister(Mem.OffsetRegNum));
746 }
747 bool isMemThumbRIs4() const {
748 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
749 !isARMLowRegister(Mem.BaseRegNum))
750 return false;
751 // Immediate offset, multiple of 4 in range [0, 124].
752 if (!Mem.OffsetImm) return true;
753 int64_t Val = Mem.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000754 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
755 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000756 bool isMemThumbRIs2() const {
757 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
758 !isARMLowRegister(Mem.BaseRegNum))
759 return false;
760 // Immediate offset, multiple of 4 in range [0, 62].
761 if (!Mem.OffsetImm) return true;
762 int64_t Val = Mem.OffsetImm->getValue();
763 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
764 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000765 bool isMemThumbRIs1() const {
766 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
767 !isARMLowRegister(Mem.BaseRegNum))
768 return false;
769 // Immediate offset in range [0, 31].
770 if (!Mem.OffsetImm) return true;
771 int64_t Val = Mem.OffsetImm->getValue();
772 return Val >= 0 && Val <= 31;
773 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000774 bool isMemThumbSPI() const {
775 if (Kind != Memory || Mem.OffsetRegNum != 0 || Mem.BaseRegNum != ARM::SP)
776 return false;
777 // Immediate offset, multiple of 4 in range [0, 1020].
778 if (!Mem.OffsetImm) return true;
779 int64_t Val = Mem.OffsetImm->getValue();
780 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000781 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000782 bool isMemImm8s4Offset() const {
783 if (Kind != Memory || Mem.OffsetRegNum != 0)
784 return false;
785 // Immediate offset a multiple of 4 in range [-1020, 1020].
786 if (!Mem.OffsetImm) return true;
787 int64_t Val = Mem.OffsetImm->getValue();
788 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
789 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000790 bool isMemImm0_1020s4Offset() const {
791 if (Kind != Memory || Mem.OffsetRegNum != 0)
792 return false;
793 // Immediate offset a multiple of 4 in range [0, 1020].
794 if (!Mem.OffsetImm) return true;
795 int64_t Val = Mem.OffsetImm->getValue();
796 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
797 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000798 bool isMemImm8Offset() const {
799 if (Kind != Memory || Mem.OffsetRegNum != 0)
800 return false;
801 // Immediate offset in range [-255, 255].
802 if (!Mem.OffsetImm) return true;
803 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000804 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000805 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000806 bool isMemPosImm8Offset() const {
807 if (Kind != Memory || Mem.OffsetRegNum != 0)
808 return false;
809 // Immediate offset in range [0, 255].
810 if (!Mem.OffsetImm) return true;
811 int64_t Val = Mem.OffsetImm->getValue();
812 return Val >= 0 && Val < 256;
813 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000814 bool isMemNegImm8Offset() const {
815 if (Kind != Memory || Mem.OffsetRegNum != 0)
816 return false;
817 // Immediate offset in range [-255, -1].
818 if (!Mem.OffsetImm) return true;
819 int64_t Val = Mem.OffsetImm->getValue();
820 return Val > -256 && Val < 0;
821 }
822 bool isMemUImm12Offset() const {
823 // If we have an immediate that's not a constant, treat it as a label
824 // reference needing a fixup. If it is a constant, it's something else
825 // and we reject it.
826 if (Kind == Immediate && !isa<MCConstantExpr>(getImm()))
827 return true;
828
829 if (Kind != Memory || Mem.OffsetRegNum != 0)
830 return false;
831 // Immediate offset in range [0, 4095].
832 if (!Mem.OffsetImm) return true;
833 int64_t Val = Mem.OffsetImm->getValue();
834 return (Val >= 0 && Val < 4096);
835 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000836 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000837 // If we have an immediate that's not a constant, treat it as a label
838 // reference needing a fixup. If it is a constant, it's something else
839 // and we reject it.
840 if (Kind == Immediate && !isa<MCConstantExpr>(getImm()))
841 return true;
842
Jim Grosbachd3595712011-08-03 23:50:40 +0000843 if (Kind != Memory || Mem.OffsetRegNum != 0)
844 return false;
845 // Immediate offset in range [-4095, 4095].
846 if (!Mem.OffsetImm) return true;
847 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000848 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000849 }
850 bool isPostIdxImm8() const {
851 if (Kind != Immediate)
852 return false;
853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
854 if (!CE) return false;
855 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000856 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000857 }
858
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000859 bool isMSRMask() const { return Kind == MSRMask; }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000860 bool isProcIFlags() const { return Kind == ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000861
862 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +0000863 // Add as immediates when possible. Null MCExpr = 0.
864 if (Expr == 0)
865 Inst.addOperand(MCOperand::CreateImm(0));
866 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000867 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
868 else
869 Inst.addOperand(MCOperand::CreateExpr(Expr));
870 }
871
Daniel Dunbard8042b72010-08-11 06:36:53 +0000872 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +0000873 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000874 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +0000875 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
876 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +0000877 }
878
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000879 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
881 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
882 }
883
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000884 void addITMaskOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
886 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
887 }
888
889 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
891 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
892 }
893
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000894 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
896 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
897 }
898
Jim Grosbach0bfb4d52010-12-06 18:21:12 +0000899 void addCCOutOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
901 Inst.addOperand(MCOperand::CreateReg(getReg()));
902 }
903
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000904 void addRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
906 Inst.addOperand(MCOperand::CreateReg(getReg()));
907 }
908
Jim Grosbachac798e12011-07-25 20:49:51 +0000909 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000910 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +0000911 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
912 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
913 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000914 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +0000915 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000916 }
917
Jim Grosbachac798e12011-07-25 20:49:51 +0000918 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +0000919 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +0000920 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
921 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +0000922 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +0000923 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +0000924 }
925
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000926 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000928 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
929 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000930 }
931
Bill Wendling8d2aa032010-11-08 23:49:57 +0000932 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +0000933 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +0000934 const SmallVectorImpl<unsigned> &RegList = getRegList();
935 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +0000936 I = RegList.begin(), E = RegList.end(); I != E; ++I)
937 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +0000938 }
939
Bill Wendling9898ac92010-11-17 04:32:08 +0000940 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
941 addRegListOperands(Inst, N);
942 }
943
944 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
945 addRegListOperands(Inst, N);
946 }
947
Jim Grosbach833b9d32011-07-27 20:15:40 +0000948 void addRotImmOperands(MCInst &Inst, unsigned N) const {
949 assert(N == 1 && "Invalid number of operands!");
950 // Encoded as val>>3. The printer handles display as 8, 16, 24.
951 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
952 }
953
Jim Grosbach864b6092011-07-28 21:34:26 +0000954 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
955 assert(N == 1 && "Invalid number of operands!");
956 // Munge the lsb/width into a bitfield mask.
957 unsigned lsb = Bitfield.LSB;
958 unsigned width = Bitfield.Width;
959 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
960 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
961 (32 - (lsb + width)));
962 Inst.addOperand(MCOperand::CreateImm(Mask));
963 }
964
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000965 void addImmOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
967 addExpr(Inst, getImm());
968 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000969
Jim Grosbache7fbce72011-10-03 23:38:36 +0000970 void addFPImmOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
972 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
973 }
974
Jim Grosbach7db8d692011-09-08 22:07:06 +0000975 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
976 assert(N == 1 && "Invalid number of operands!");
977 // FIXME: We really want to scale the value here, but the LDRD/STRD
978 // instruction don't encode operands that way yet.
979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
980 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
981 }
982
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000983 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
985 // The immediate is scaled by four in the encoding and is stored
986 // in the MCInst as such. Lop off the low two bits here.
987 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
988 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
989 }
990
991 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
992 assert(N == 1 && "Invalid number of operands!");
993 // The immediate is scaled by four in the encoding and is stored
994 // in the MCInst as such. Lop off the low two bits here.
995 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
996 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
997 }
998
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000999 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
1001 addExpr(Inst, getImm());
1002 }
1003
Jim Grosbach31756c22011-07-13 22:01:08 +00001004 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006 addExpr(Inst, getImm());
1007 }
1008
1009 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
1011 addExpr(Inst, getImm());
1012 }
1013
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001014 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
1016 addExpr(Inst, getImm());
1017 }
1018
Jim Grosbach475c6db2011-07-25 23:09:14 +00001019 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
1021 // The constant encodes as the immediate-1, and we store in the instruction
1022 // the bits as encoded, so subtract off one here.
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1025 }
1026
Jim Grosbach801e0a32011-07-22 23:16:18 +00001027 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 // The constant encodes as the immediate-1, and we store in the instruction
1030 // the bits as encoded, so subtract off one here.
1031 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1032 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1033 }
1034
Jim Grosbach975b6412011-07-13 20:10:10 +00001035 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 addExpr(Inst, getImm());
1038 }
1039
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001040 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
1042 addExpr(Inst, getImm());
1043 }
1044
Jim Grosbachf1637842011-07-26 16:24:27 +00001045 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
1047 addExpr(Inst, getImm());
1048 }
1049
Jim Grosbach46dd4132011-08-17 21:51:27 +00001050 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 // The constant encodes as the immediate, except for 32, which encodes as
1053 // zero.
1054 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1055 unsigned Imm = CE->getValue();
1056 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1057 }
1058
Jim Grosbach27c1e252011-07-21 17:23:04 +00001059 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
1061 addExpr(Inst, getImm());
1062 }
1063
1064 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1065 assert(N == 1 && "Invalid number of operands!");
1066 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1067 // the instruction as well.
1068 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1069 int Val = CE->getValue();
1070 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1071 }
1072
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001073 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 addExpr(Inst, getImm());
1076 }
1077
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001078 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 addExpr(Inst, getImm());
1081 }
1082
Jim Grosbach0a547702011-07-22 17:44:50 +00001083 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1084 assert(N == 1 && "Invalid number of operands!");
1085 addExpr(Inst, getImm());
1086 }
1087
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001088 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1091 }
1092
Jim Grosbachd3595712011-08-03 23:50:40 +00001093 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
1095 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001096 }
1097
Jim Grosbachd3595712011-08-03 23:50:40 +00001098 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1099 assert(N == 3 && "Invalid number of operands!");
1100 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1101 if (!Mem.OffsetRegNum) {
1102 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1103 // Special case for #-0
1104 if (Val == INT32_MIN) Val = 0;
1105 if (Val < 0) Val = -Val;
1106 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1107 } else {
1108 // For register offset, we encode the shift type and negation flag
1109 // here.
1110 Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbacha2b8b602011-08-11 22:05:09 +00001111 Mem.ShiftImm, Mem.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001112 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001113 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1114 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1115 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001116 }
1117
Jim Grosbachcd17c122011-08-04 23:01:30 +00001118 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 2 && "Invalid number of operands!");
1120 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1121 assert(CE && "non-constant AM2OffsetImm operand!");
1122 int32_t Val = CE->getValue();
1123 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1124 // Special case for #-0
1125 if (Val == INT32_MIN) Val = 0;
1126 if (Val < 0) Val = -Val;
1127 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1128 Inst.addOperand(MCOperand::CreateReg(0));
1129 Inst.addOperand(MCOperand::CreateImm(Val));
1130 }
1131
Jim Grosbach5b96b802011-08-10 20:29:19 +00001132 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1133 assert(N == 3 && "Invalid number of operands!");
1134 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1135 if (!Mem.OffsetRegNum) {
1136 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1137 // Special case for #-0
1138 if (Val == INT32_MIN) Val = 0;
1139 if (Val < 0) Val = -Val;
1140 Val = ARM_AM::getAM3Opc(AddSub, Val);
1141 } else {
1142 // For register offset, we encode the shift type and negation flag
1143 // here.
1144 Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
1145 }
1146 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1147 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1148 Inst.addOperand(MCOperand::CreateImm(Val));
1149 }
1150
1151 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1152 assert(N == 2 && "Invalid number of operands!");
1153 if (Kind == PostIndexRegister) {
1154 int32_t Val =
1155 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1156 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1157 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001158 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001159 }
1160
1161 // Constant offset.
1162 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1163 int32_t Val = CE->getValue();
1164 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1165 // Special case for #-0
1166 if (Val == INT32_MIN) Val = 0;
1167 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001168 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001169 Inst.addOperand(MCOperand::CreateReg(0));
1170 Inst.addOperand(MCOperand::CreateImm(Val));
1171 }
1172
Jim Grosbachd3595712011-08-03 23:50:40 +00001173 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1174 assert(N == 2 && "Invalid number of operands!");
1175 // The lower two bits are always zero and as such are not encoded.
1176 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1177 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1178 // Special case for #-0
1179 if (Val == INT32_MIN) Val = 0;
1180 if (Val < 0) Val = -Val;
1181 Val = ARM_AM::getAM5Opc(AddSub, Val);
1182 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1183 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001184 }
1185
Jim Grosbach7db8d692011-09-08 22:07:06 +00001186 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 2 && "Invalid number of operands!");
1188 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1189 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1190 Inst.addOperand(MCOperand::CreateImm(Val));
1191 }
1192
Jim Grosbacha05627e2011-09-09 18:37:27 +00001193 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1194 assert(N == 2 && "Invalid number of operands!");
1195 // The lower two bits are always zero and as such are not encoded.
1196 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1197 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1198 Inst.addOperand(MCOperand::CreateImm(Val));
1199 }
1200
Jim Grosbachd3595712011-08-03 23:50:40 +00001201 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 2 && "Invalid number of operands!");
1203 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1204 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1205 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001206 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001207
Jim Grosbach2392c532011-09-07 23:39:14 +00001208 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1209 addMemImm8OffsetOperands(Inst, N);
1210 }
1211
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001212 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001213 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001214 }
1215
1216 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 2 && "Invalid number of operands!");
1218 // If this is an immediate, it's a label reference.
1219 if (Kind == Immediate) {
1220 addExpr(Inst, getImm());
1221 Inst.addOperand(MCOperand::CreateImm(0));
1222 return;
1223 }
1224
1225 // Otherwise, it's a normal memory reg+offset.
1226 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1227 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1228 Inst.addOperand(MCOperand::CreateImm(Val));
1229 }
1230
Jim Grosbachd3595712011-08-03 23:50:40 +00001231 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001233 // If this is an immediate, it's a label reference.
1234 if (Kind == Immediate) {
1235 addExpr(Inst, getImm());
1236 Inst.addOperand(MCOperand::CreateImm(0));
1237 return;
1238 }
1239
1240 // Otherwise, it's a normal memory reg+offset.
Jim Grosbachd3595712011-08-03 23:50:40 +00001241 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1242 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1243 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001244 }
Bill Wendling811c9362010-11-30 07:44:32 +00001245
Jim Grosbach05541f42011-09-19 22:21:13 +00001246 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 2 && "Invalid number of operands!");
1248 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1249 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1250 }
1251
1252 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 2 && "Invalid number of operands!");
1254 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1255 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1256 }
1257
Jim Grosbachd3595712011-08-03 23:50:40 +00001258 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1259 assert(N == 3 && "Invalid number of operands!");
1260 unsigned Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001261 Mem.ShiftImm, Mem.ShiftType);
Jim Grosbachd3595712011-08-03 23:50:40 +00001262 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1263 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1264 Inst.addOperand(MCOperand::CreateImm(Val));
1265 }
1266
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001267 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1268 assert(N == 3 && "Invalid number of operands!");
1269 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1270 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1271 Inst.addOperand(MCOperand::CreateImm(Mem.ShiftImm));
1272 }
1273
Jim Grosbachd3595712011-08-03 23:50:40 +00001274 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1275 assert(N == 2 && "Invalid number of operands!");
1276 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1277 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1278 }
1279
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001280 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1283 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1284 Inst.addOperand(MCOperand::CreateImm(Val));
1285 }
1286
Jim Grosbach26d35872011-08-19 18:55:51 +00001287 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1288 assert(N == 2 && "Invalid number of operands!");
1289 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 2) : 0;
1290 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1291 Inst.addOperand(MCOperand::CreateImm(Val));
1292 }
1293
Jim Grosbacha32c7532011-08-19 18:49:59 +00001294 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 2 && "Invalid number of operands!");
1296 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue()) : 0;
1297 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1298 Inst.addOperand(MCOperand::CreateImm(Val));
1299 }
1300
Jim Grosbach23983d62011-08-19 18:13:48 +00001301 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1302 assert(N == 2 && "Invalid number of operands!");
1303 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1304 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1305 Inst.addOperand(MCOperand::CreateImm(Val));
1306 }
1307
Jim Grosbachd3595712011-08-03 23:50:40 +00001308 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
1310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1311 assert(CE && "non-constant post-idx-imm8 operand!");
1312 int Imm = CE->getValue();
1313 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001314 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001315 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1316 Inst.addOperand(MCOperand::CreateImm(Imm));
1317 }
1318
1319 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1320 assert(N == 2 && "Invalid number of operands!");
1321 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001322 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1323 }
1324
1325 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1326 assert(N == 2 && "Invalid number of operands!");
1327 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1328 // The sign, shift type, and shift amount are encoded in a single operand
1329 // using the AM2 encoding helpers.
1330 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1331 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1332 PostIdxReg.ShiftTy);
1333 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001334 }
1335
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001336 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1337 assert(N == 1 && "Invalid number of operands!");
1338 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1339 }
1340
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001341 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1342 assert(N == 1 && "Invalid number of operands!");
1343 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1344 }
1345
Jim Grosbach602aa902011-07-13 15:34:57 +00001346 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001347
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001348 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
1349 ARMOperand *Op = new ARMOperand(ITCondMask);
1350 Op->ITMask.Mask = Mask;
1351 Op->StartLoc = S;
1352 Op->EndLoc = S;
1353 return Op;
1354 }
1355
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001356 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
1357 ARMOperand *Op = new ARMOperand(CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001358 Op->CC.Val = CC;
1359 Op->StartLoc = S;
1360 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001361 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001362 }
1363
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001364 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
1365 ARMOperand *Op = new ARMOperand(CoprocNum);
1366 Op->Cop.Val = CopVal;
1367 Op->StartLoc = S;
1368 Op->EndLoc = S;
1369 return Op;
1370 }
1371
1372 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
1373 ARMOperand *Op = new ARMOperand(CoprocReg);
1374 Op->Cop.Val = CopVal;
1375 Op->StartLoc = S;
1376 Op->EndLoc = S;
1377 return Op;
1378 }
1379
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001380 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
1381 ARMOperand *Op = new ARMOperand(CCOut);
1382 Op->Reg.RegNum = RegNum;
1383 Op->StartLoc = S;
1384 Op->EndLoc = S;
1385 return Op;
1386 }
1387
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001388 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
1389 ARMOperand *Op = new ARMOperand(Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001390 Op->Tok.Data = Str.data();
1391 Op->Tok.Length = Str.size();
1392 Op->StartLoc = S;
1393 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001394 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001395 }
1396
Bill Wendling2063b842010-11-18 23:43:05 +00001397 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001398 ARMOperand *Op = new ARMOperand(Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001399 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001400 Op->StartLoc = S;
1401 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001402 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001403 }
1404
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001405 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1406 unsigned SrcReg,
1407 unsigned ShiftReg,
1408 unsigned ShiftImm,
1409 SMLoc S, SMLoc E) {
1410 ARMOperand *Op = new ARMOperand(ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001411 Op->RegShiftedReg.ShiftTy = ShTy;
1412 Op->RegShiftedReg.SrcReg = SrcReg;
1413 Op->RegShiftedReg.ShiftReg = ShiftReg;
1414 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001415 Op->StartLoc = S;
1416 Op->EndLoc = E;
1417 return Op;
1418 }
1419
Owen Andersonb595ed02011-07-21 18:54:16 +00001420 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1421 unsigned SrcReg,
1422 unsigned ShiftImm,
1423 SMLoc S, SMLoc E) {
1424 ARMOperand *Op = new ARMOperand(ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001425 Op->RegShiftedImm.ShiftTy = ShTy;
1426 Op->RegShiftedImm.SrcReg = SrcReg;
1427 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001428 Op->StartLoc = S;
1429 Op->EndLoc = E;
1430 return Op;
1431 }
1432
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001433 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001434 SMLoc S, SMLoc E) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001435 ARMOperand *Op = new ARMOperand(ShifterImmediate);
1436 Op->ShifterImm.isASR = isASR;
1437 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001438 Op->StartLoc = S;
1439 Op->EndLoc = E;
1440 return Op;
1441 }
1442
Jim Grosbach833b9d32011-07-27 20:15:40 +00001443 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
1444 ARMOperand *Op = new ARMOperand(RotateImmediate);
1445 Op->RotImm.Imm = Imm;
1446 Op->StartLoc = S;
1447 Op->EndLoc = E;
1448 return Op;
1449 }
1450
Jim Grosbach864b6092011-07-28 21:34:26 +00001451 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1452 SMLoc S, SMLoc E) {
1453 ARMOperand *Op = new ARMOperand(BitfieldDescriptor);
1454 Op->Bitfield.LSB = LSB;
1455 Op->Bitfield.Width = Width;
1456 Op->StartLoc = S;
1457 Op->EndLoc = E;
1458 return Op;
1459 }
1460
Bill Wendling2cae3272010-11-09 22:44:22 +00001461 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001462 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001463 SMLoc StartLoc, SMLoc EndLoc) {
Bill Wendling9898ac92010-11-17 04:32:08 +00001464 KindTy Kind = RegisterList;
1465
Jim Grosbach75461af2011-09-13 22:56:44 +00001466 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Bill Wendling9898ac92010-11-17 04:32:08 +00001467 Kind = DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001468 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001469 contains(Regs.front().first))
Bill Wendling9898ac92010-11-17 04:32:08 +00001470 Kind = SPRRegisterList;
1471
1472 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001473 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001474 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001475 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001476 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001477 Op->StartLoc = StartLoc;
1478 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001479 return Op;
1480 }
1481
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001482 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
1483 ARMOperand *Op = new ARMOperand(Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001484 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001485 Op->StartLoc = S;
1486 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001487 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001488 }
1489
Jim Grosbache7fbce72011-10-03 23:38:36 +00001490 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
1491 ARMOperand *Op = new ARMOperand(FPImmediate);
1492 Op->FPImm.Val = Val;
1493 Op->StartLoc = S;
1494 Op->EndLoc = S;
1495 return Op;
1496 }
1497
Jim Grosbachd3595712011-08-03 23:50:40 +00001498 static ARMOperand *CreateMem(unsigned BaseRegNum,
1499 const MCConstantExpr *OffsetImm,
1500 unsigned OffsetRegNum,
1501 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001502 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001503 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001504 SMLoc S, SMLoc E) {
1505 ARMOperand *Op = new ARMOperand(Memory);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001506 Op->Mem.BaseRegNum = BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +00001507 Op->Mem.OffsetImm = OffsetImm;
1508 Op->Mem.OffsetRegNum = OffsetRegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001509 Op->Mem.ShiftType = ShiftType;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001510 Op->Mem.ShiftImm = ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +00001511 Op->Mem.isNegative = isNegative;
1512 Op->StartLoc = S;
1513 Op->EndLoc = E;
1514 return Op;
1515 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001516
Jim Grosbachc320c852011-08-05 21:28:30 +00001517 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1518 ARM_AM::ShiftOpc ShiftTy,
1519 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001520 SMLoc S, SMLoc E) {
1521 ARMOperand *Op = new ARMOperand(PostIndexRegister);
1522 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001523 Op->PostIdxReg.isAdd = isAdd;
1524 Op->PostIdxReg.ShiftTy = ShiftTy;
1525 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001526 Op->StartLoc = S;
1527 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001528 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001529 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001530
1531 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
1532 ARMOperand *Op = new ARMOperand(MemBarrierOpt);
1533 Op->MBOpt.Val = Opt;
1534 Op->StartLoc = S;
1535 Op->EndLoc = S;
1536 return Op;
1537 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001538
1539 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
1540 ARMOperand *Op = new ARMOperand(ProcIFlags);
1541 Op->IFlags.Val = IFlags;
1542 Op->StartLoc = S;
1543 Op->EndLoc = S;
1544 return Op;
1545 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001546
1547 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
1548 ARMOperand *Op = new ARMOperand(MSRMask);
1549 Op->MMask.Val = MMask;
1550 Op->StartLoc = S;
1551 Op->EndLoc = S;
1552 return Op;
1553 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001554};
1555
1556} // end anonymous namespace.
1557
Jim Grosbach602aa902011-07-13 15:34:57 +00001558void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001559 switch (Kind) {
Jim Grosbache7fbce72011-10-03 23:38:36 +00001560 case FPImmediate:
1561 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1562 << ") >";
1563 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001564 case CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001565 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001566 break;
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001567 case CCOut:
1568 OS << "<ccout " << getReg() << ">";
1569 break;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001570 case ITCondMask: {
1571 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1572 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1573 "(tee)", "(eee)" };
1574 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1575 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1576 break;
1577 }
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001578 case CoprocNum:
1579 OS << "<coprocessor number: " << getCoproc() << ">";
1580 break;
1581 case CoprocReg:
1582 OS << "<coprocessor register: " << getCoproc() << ">";
1583 break;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001584 case MSRMask:
1585 OS << "<mask: " << getMSRMask() << ">";
1586 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001587 case Immediate:
1588 getImm()->print(OS);
1589 break;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001590 case MemBarrierOpt:
1591 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1592 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001593 case Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001594 OS << "<memory "
Jim Grosbachd3595712011-08-03 23:50:40 +00001595 << " base:" << Mem.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001596 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001597 break;
Jim Grosbachd3595712011-08-03 23:50:40 +00001598 case PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001599 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1600 << PostIdxReg.RegNum;
1601 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1602 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1603 << PostIdxReg.ShiftImm;
1604 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001605 break;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001606 case ProcIFlags: {
1607 OS << "<ARM_PROC::";
1608 unsigned IFlags = getProcIFlags();
1609 for (int i=2; i >= 0; --i)
1610 if (IFlags & (1 << i))
1611 OS << ARM_PROC::IFlagsToString(1 << i);
1612 OS << ">";
1613 break;
1614 }
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001615 case Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001616 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001617 break;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001618 case ShifterImmediate:
1619 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1620 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001621 break;
1622 case ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001623 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001624 << RegShiftedReg.SrcReg
1625 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1626 << ", " << RegShiftedReg.ShiftReg << ", "
1627 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001628 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001629 break;
Owen Andersonb595ed02011-07-21 18:54:16 +00001630 case ShiftedImmediate:
1631 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001632 << RegShiftedImm.SrcReg
1633 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1634 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001635 << ">";
1636 break;
Jim Grosbach833b9d32011-07-27 20:15:40 +00001637 case RotateImmediate:
1638 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1639 break;
Jim Grosbach864b6092011-07-28 21:34:26 +00001640 case BitfieldDescriptor:
1641 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1642 << ", width: " << Bitfield.Width << ">";
1643 break;
Bill Wendling9898ac92010-11-17 04:32:08 +00001644 case RegisterList:
1645 case DPRRegisterList:
1646 case SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001647 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001648
Bill Wendlingbed94652010-11-09 23:28:44 +00001649 const SmallVectorImpl<unsigned> &RegList = getRegList();
1650 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001651 I = RegList.begin(), E = RegList.end(); I != E; ) {
1652 OS << *I;
1653 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001654 }
1655
1656 OS << ">";
1657 break;
1658 }
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001659 case Token:
1660 OS << "'" << getToken() << "'";
1661 break;
1662 }
1663}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001664
1665/// @name Auto-generated Match Functions
1666/// {
1667
1668static unsigned MatchRegisterName(StringRef Name);
1669
1670/// }
1671
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001672bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1673 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001674 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00001675
1676 return (RegNo == (unsigned)-1);
1677}
1678
Kevin Enderby8be42bd2009-10-30 22:55:57 +00001679/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00001680/// and if it is a register name the token is eaten and the register number is
1681/// returned. Otherwise return -1.
1682///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001683int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00001684 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00001685 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00001686
Chris Lattner44e5981c2010-10-30 04:09:10 +00001687 // FIXME: Validate register for the current architecture; we have to do
1688 // validation later, so maybe there is no need for this here.
Owen Andersona098d152011-01-13 22:50:36 +00001689 std::string upperCase = Tok.getString().str();
1690 std::string lowerCase = LowercaseString(upperCase);
1691 unsigned RegNum = MatchRegisterName(lowerCase);
1692 if (!RegNum) {
1693 RegNum = StringSwitch<unsigned>(lowerCase)
1694 .Case("r13", ARM::SP)
1695 .Case("r14", ARM::LR)
1696 .Case("r15", ARM::PC)
1697 .Case("ip", ARM::R12)
1698 .Default(0);
1699 }
1700 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001701
Chris Lattner44e5981c2010-10-30 04:09:10 +00001702 Parser.Lex(); // Eat identifier token.
1703 return RegNum;
1704}
Jim Grosbach99710a82010-11-01 16:44:21 +00001705
Jim Grosbachbb24c592011-07-13 18:49:30 +00001706// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1707// If a recoverable error occurs, return 1. If an irrecoverable error
1708// occurs, return -1. An irrecoverable error is one where tokens have been
1709// consumed in the process of trying to parse the shifter (i.e., when it is
1710// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00001711int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001712 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1713 SMLoc S = Parser.getTok().getLoc();
1714 const AsmToken &Tok = Parser.getTok();
1715 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1716
1717 std::string upperCase = Tok.getString().str();
1718 std::string lowerCase = LowercaseString(upperCase);
1719 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1720 .Case("lsl", ARM_AM::lsl)
1721 .Case("lsr", ARM_AM::lsr)
1722 .Case("asr", ARM_AM::asr)
1723 .Case("ror", ARM_AM::ror)
1724 .Case("rrx", ARM_AM::rrx)
1725 .Default(ARM_AM::no_shift);
1726
1727 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00001728 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001729
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001730 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001731
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001732 // The source register for the shift has already been added to the
1733 // operand list, so we need to pop it off and combine it into the shifted
1734 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00001735 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001736 if (!PrevOp->isReg())
1737 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1738 int SrcReg = PrevOp->getReg();
1739 int64_t Imm = 0;
1740 int ShiftReg = 0;
1741 if (ShiftTy == ARM_AM::rrx) {
1742 // RRX Doesn't have an explicit shift amount. The encoder expects
1743 // the shift register to be the same as the source register. Seems odd,
1744 // but OK.
1745 ShiftReg = SrcReg;
1746 } else {
1747 // Figure out if this is shifted by a constant or a register (for non-RRX).
1748 if (Parser.getTok().is(AsmToken::Hash)) {
1749 Parser.Lex(); // Eat hash.
1750 SMLoc ImmLoc = Parser.getTok().getLoc();
1751 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00001752 if (getParser().ParseExpression(ShiftExpr)) {
1753 Error(ImmLoc, "invalid immediate shift value");
1754 return -1;
1755 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001756 // The expression must be evaluatable as an immediate.
1757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00001758 if (!CE) {
1759 Error(ImmLoc, "invalid immediate shift value");
1760 return -1;
1761 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001762 // Range check the immediate.
1763 // lsl, ror: 0 <= imm <= 31
1764 // lsr, asr: 0 <= imm <= 32
1765 Imm = CE->getValue();
1766 if (Imm < 0 ||
1767 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1768 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00001769 Error(ImmLoc, "immediate shift value out of range");
1770 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001771 }
1772 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001773 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001774 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00001775 if (ShiftReg == -1) {
1776 Error (L, "expected immediate or register in shift operand");
1777 return -1;
1778 }
1779 } else {
1780 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001781 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00001782 return -1;
1783 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001784 }
1785
Owen Andersonb595ed02011-07-21 18:54:16 +00001786 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1787 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00001788 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001789 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00001790 else
1791 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1792 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001793
Jim Grosbachbb24c592011-07-13 18:49:30 +00001794 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001795}
1796
1797
Bill Wendling2063b842010-11-18 23:43:05 +00001798/// Try to parse a register name. The token must be an Identifier when called.
1799/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1800/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001801///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00001802/// TODO this is likely to change to allow different register types and or to
1803/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00001804bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001805tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00001806 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001807 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00001808 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00001809 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00001810
Bill Wendling2063b842010-11-18 23:43:05 +00001811 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001812
Chris Lattner44e5981c2010-10-30 04:09:10 +00001813 const AsmToken &ExclaimTok = Parser.getTok();
1814 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00001815 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1816 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00001817 Parser.Lex(); // Eat exclaim token
Kevin Enderby2207e5f2009-10-07 18:01:35 +00001818 }
1819
Bill Wendling2063b842010-11-18 23:43:05 +00001820 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001821}
1822
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001823/// MatchCoprocessorOperandName - Try to parse an coprocessor related
1824/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
1825/// "c5", ...
1826static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001827 // Use the same layout as the tablegen'erated register name matcher. Ugly,
1828 // but efficient.
1829 switch (Name.size()) {
1830 default: break;
1831 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001832 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001833 return -1;
1834 switch (Name[1]) {
1835 default: return -1;
1836 case '0': return 0;
1837 case '1': return 1;
1838 case '2': return 2;
1839 case '3': return 3;
1840 case '4': return 4;
1841 case '5': return 5;
1842 case '6': return 6;
1843 case '7': return 7;
1844 case '8': return 8;
1845 case '9': return 9;
1846 }
1847 break;
1848 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001849 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001850 return -1;
1851 switch (Name[2]) {
1852 default: return -1;
1853 case '0': return 10;
1854 case '1': return 11;
1855 case '2': return 12;
1856 case '3': return 13;
1857 case '4': return 14;
1858 case '5': return 15;
1859 }
1860 break;
1861 }
1862
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001863 return -1;
1864}
1865
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001866/// parseITCondCode - Try to parse a condition code for an IT instruction.
1867ARMAsmParser::OperandMatchResultTy ARMAsmParser::
1868parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1869 SMLoc S = Parser.getTok().getLoc();
1870 const AsmToken &Tok = Parser.getTok();
1871 if (!Tok.is(AsmToken::Identifier))
1872 return MatchOperand_NoMatch;
1873 unsigned CC = StringSwitch<unsigned>(Tok.getString())
1874 .Case("eq", ARMCC::EQ)
1875 .Case("ne", ARMCC::NE)
1876 .Case("hs", ARMCC::HS)
1877 .Case("cs", ARMCC::HS)
1878 .Case("lo", ARMCC::LO)
1879 .Case("cc", ARMCC::LO)
1880 .Case("mi", ARMCC::MI)
1881 .Case("pl", ARMCC::PL)
1882 .Case("vs", ARMCC::VS)
1883 .Case("vc", ARMCC::VC)
1884 .Case("hi", ARMCC::HI)
1885 .Case("ls", ARMCC::LS)
1886 .Case("ge", ARMCC::GE)
1887 .Case("lt", ARMCC::LT)
1888 .Case("gt", ARMCC::GT)
1889 .Case("le", ARMCC::LE)
1890 .Case("al", ARMCC::AL)
1891 .Default(~0U);
1892 if (CC == ~0U)
1893 return MatchOperand_NoMatch;
1894 Parser.Lex(); // Eat the token.
1895
1896 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
1897
1898 return MatchOperand_Success;
1899}
1900
Jim Grosbach2d6ef442011-07-25 20:14:50 +00001901/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001902/// token must be an Identifier when called, and if it is a coprocessor
1903/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00001904ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00001905parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001906 SMLoc S = Parser.getTok().getLoc();
1907 const AsmToken &Tok = Parser.getTok();
1908 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1909
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001910 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001911 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00001912 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001913
1914 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001915 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00001916 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001917}
1918
Jim Grosbach2d6ef442011-07-25 20:14:50 +00001919/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001920/// token must be an Identifier when called, and if it is a coprocessor
1921/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00001922ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00001923parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001924 SMLoc S = Parser.getTok().getLoc();
1925 const AsmToken &Tok = Parser.getTok();
1926 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1927
1928 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
1929 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00001930 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001931
1932 Parser.Lex(); // Eat identifier token.
1933 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00001934 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00001935}
1936
Jim Grosbach3ac26b12011-09-14 18:08:35 +00001937// For register list parsing, we need to map from raw GPR register numbering
1938// to the enumeration values. The enumeration values aren't sorted by
1939// register number due to our using "sp", "lr" and "pc" as canonical names.
1940static unsigned getNextRegister(unsigned Reg) {
1941 // If this is a GPR, we need to do it manually, otherwise we can rely
1942 // on the sort ordering of the enumeration since the other reg-classes
1943 // are sane.
1944 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
1945 return Reg + 1;
1946 switch(Reg) {
1947 default: assert(0 && "Invalid GPR number!");
1948 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
1949 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
1950 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
1951 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
1952 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
1953 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
1954 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
1955 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
1956 }
1957}
1958
1959/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00001960bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001961parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00001962 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00001963 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00001964 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00001965 Parser.Lex(); // Eat '{' token.
1966 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00001967
Jim Grosbach3ac26b12011-09-14 18:08:35 +00001968 // Check the first register in the list to see what register class
1969 // this is a list of.
1970 int Reg = tryParseRegister();
1971 if (Reg == -1)
1972 return Error(RegLoc, "register expected");
1973
1974 MCRegisterClass *RC;
1975 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
1976 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
1977 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
1978 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
1979 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
1980 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
1981 else
1982 return Error(RegLoc, "invalid register in register list");
1983
1984 // The reglist instructions have at most 16 registers, so reserve
1985 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00001986 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00001987 // Store the first register.
1988 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00001989
Jim Grosbach3ac26b12011-09-14 18:08:35 +00001990 // This starts immediately after the first register token in the list,
1991 // so we can see either a comma or a minus (range separator) as a legal
1992 // next token.
1993 while (Parser.getTok().is(AsmToken::Comma) ||
1994 Parser.getTok().is(AsmToken::Minus)) {
1995 if (Parser.getTok().is(AsmToken::Minus)) {
1996 Parser.Lex(); // Eat the comma.
1997 SMLoc EndLoc = Parser.getTok().getLoc();
1998 int EndReg = tryParseRegister();
1999 if (EndReg == -1)
2000 return Error(EndLoc, "register expected");
2001 // If the register is the same as the start reg, there's nothing
2002 // more to do.
2003 if (Reg == EndReg)
2004 continue;
2005 // The register must be in the same register class as the first.
2006 if (!RC->contains(EndReg))
2007 return Error(EndLoc, "invalid register in register list");
2008 // Ranges must go from low to high.
2009 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2010 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002011
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002012 // Add all the registers in the range to the register list.
2013 while (Reg != EndReg) {
2014 Reg = getNextRegister(Reg);
2015 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2016 }
2017 continue;
2018 }
2019 Parser.Lex(); // Eat the comma.
2020 RegLoc = Parser.getTok().getLoc();
2021 int OldReg = Reg;
2022 Reg = tryParseRegister();
2023 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002024 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002025 // The register must be in the same register class as the first.
2026 if (!RC->contains(Reg))
2027 return Error(RegLoc, "invalid register in register list");
2028 // List must be monotonically increasing.
2029 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2030 return Error(RegLoc, "register list not in ascending order");
2031 // VFP register lists must also be contiguous.
2032 // It's OK to use the enumeration values directly here rather, as the
2033 // VFP register classes have the enum sorted properly.
2034 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2035 Reg != OldReg + 1)
2036 return Error(RegLoc, "non-contiguous register range");
2037 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002038 }
2039
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002040 SMLoc E = Parser.getTok().getLoc();
2041 if (Parser.getTok().isNot(AsmToken::RCurly))
2042 return Error(E, "'}' expected");
2043 Parser.Lex(); // Eat '}' token.
2044
Bill Wendling2063b842010-11-18 23:43:05 +00002045 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2046 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002047}
2048
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002049/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002050ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002051parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002052 SMLoc S = Parser.getTok().getLoc();
2053 const AsmToken &Tok = Parser.getTok();
2054 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2055 StringRef OptStr = Tok.getString();
2056
2057 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2058 .Case("sy", ARM_MB::SY)
2059 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002060 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002061 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002062 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002063 .Case("ishst", ARM_MB::ISHST)
2064 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002065 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002066 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002067 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002068 .Case("osh", ARM_MB::OSH)
2069 .Case("oshst", ARM_MB::OSHST)
2070 .Default(~0U);
2071
2072 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002073 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002074
2075 Parser.Lex(); // Eat identifier token.
2076 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002077 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002078}
2079
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002080/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002081ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002082parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002083 SMLoc S = Parser.getTok().getLoc();
2084 const AsmToken &Tok = Parser.getTok();
2085 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2086 StringRef IFlagsStr = Tok.getString();
2087
2088 unsigned IFlags = 0;
2089 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2090 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2091 .Case("a", ARM_PROC::A)
2092 .Case("i", ARM_PROC::I)
2093 .Case("f", ARM_PROC::F)
2094 .Default(~0U);
2095
2096 // If some specific iflag is already set, it means that some letter is
2097 // present more than once, this is not acceptable.
2098 if (Flag == ~0U || (IFlags & Flag))
2099 return MatchOperand_NoMatch;
2100
2101 IFlags |= Flag;
2102 }
2103
2104 Parser.Lex(); // Eat identifier token.
2105 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2106 return MatchOperand_Success;
2107}
2108
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002109/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002110ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002111parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002112 SMLoc S = Parser.getTok().getLoc();
2113 const AsmToken &Tok = Parser.getTok();
2114 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2115 StringRef Mask = Tok.getString();
2116
James Molloy21efa7d2011-09-28 14:21:38 +00002117 if (isMClass()) {
2118 // See ARMv6-M 10.1.1
2119 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2120 .Case("apsr", 0)
2121 .Case("iapsr", 1)
2122 .Case("eapsr", 2)
2123 .Case("xpsr", 3)
2124 .Case("ipsr", 5)
2125 .Case("epsr", 6)
2126 .Case("iepsr", 7)
2127 .Case("msp", 8)
2128 .Case("psp", 9)
2129 .Case("primask", 16)
2130 .Case("basepri", 17)
2131 .Case("basepri_max", 18)
2132 .Case("faultmask", 19)
2133 .Case("control", 20)
2134 .Default(~0U);
2135
2136 if (FlagsVal == ~0U)
2137 return MatchOperand_NoMatch;
2138
2139 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2140 // basepri, basepri_max and faultmask only valid for V7m.
2141 return MatchOperand_NoMatch;
2142
2143 Parser.Lex(); // Eat identifier token.
2144 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2145 return MatchOperand_Success;
2146 }
2147
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002148 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2149 size_t Start = 0, Next = Mask.find('_');
2150 StringRef Flags = "";
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002151 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002152 if (Next != StringRef::npos)
2153 Flags = Mask.slice(Next+1, Mask.size());
2154
2155 // FlagsVal contains the complete mask:
2156 // 3-0: Mask
2157 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2158 unsigned FlagsVal = 0;
2159
2160 if (SpecReg == "apsr") {
2161 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002162 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002163 .Case("g", 0x4) // same as CPSR_s
2164 .Case("nzcvqg", 0xc) // same as CPSR_fs
2165 .Default(~0U);
2166
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002167 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002168 if (!Flags.empty())
2169 return MatchOperand_NoMatch;
2170 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002171 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002172 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002173 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002174 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2175 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002176 for (int i = 0, e = Flags.size(); i != e; ++i) {
2177 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2178 .Case("c", 1)
2179 .Case("x", 2)
2180 .Case("s", 4)
2181 .Case("f", 8)
2182 .Default(~0U);
2183
2184 // If some specific flag is already set, it means that some letter is
2185 // present more than once, this is not acceptable.
2186 if (FlagsVal == ~0U || (FlagsVal & Flag))
2187 return MatchOperand_NoMatch;
2188 FlagsVal |= Flag;
2189 }
2190 } else // No match for special register.
2191 return MatchOperand_NoMatch;
2192
2193 // Special register without flags are equivalent to "fc" flags.
2194 if (!FlagsVal)
2195 FlagsVal = 0x9;
2196
2197 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2198 if (SpecReg == "spsr")
2199 FlagsVal |= 16;
2200
2201 Parser.Lex(); // Eat identifier token.
2202 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2203 return MatchOperand_Success;
2204}
2205
Jim Grosbach27c1e252011-07-21 17:23:04 +00002206ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2207parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2208 int Low, int High) {
2209 const AsmToken &Tok = Parser.getTok();
2210 if (Tok.isNot(AsmToken::Identifier)) {
2211 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2212 return MatchOperand_ParseFail;
2213 }
2214 StringRef ShiftName = Tok.getString();
2215 std::string LowerOp = LowercaseString(Op);
2216 std::string UpperOp = UppercaseString(Op);
2217 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2218 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2219 return MatchOperand_ParseFail;
2220 }
2221 Parser.Lex(); // Eat shift type token.
2222
2223 // There must be a '#' and a shift amount.
2224 if (Parser.getTok().isNot(AsmToken::Hash)) {
2225 Error(Parser.getTok().getLoc(), "'#' expected");
2226 return MatchOperand_ParseFail;
2227 }
2228 Parser.Lex(); // Eat hash token.
2229
2230 const MCExpr *ShiftAmount;
2231 SMLoc Loc = Parser.getTok().getLoc();
2232 if (getParser().ParseExpression(ShiftAmount)) {
2233 Error(Loc, "illegal expression");
2234 return MatchOperand_ParseFail;
2235 }
2236 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2237 if (!CE) {
2238 Error(Loc, "constant expression expected");
2239 return MatchOperand_ParseFail;
2240 }
2241 int Val = CE->getValue();
2242 if (Val < Low || Val > High) {
2243 Error(Loc, "immediate value out of range");
2244 return MatchOperand_ParseFail;
2245 }
2246
2247 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2248
2249 return MatchOperand_Success;
2250}
2251
Jim Grosbach0a547702011-07-22 17:44:50 +00002252ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2253parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2254 const AsmToken &Tok = Parser.getTok();
2255 SMLoc S = Tok.getLoc();
2256 if (Tok.isNot(AsmToken::Identifier)) {
2257 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2258 return MatchOperand_ParseFail;
2259 }
2260 int Val = StringSwitch<int>(Tok.getString())
2261 .Case("be", 1)
2262 .Case("le", 0)
2263 .Default(-1);
2264 Parser.Lex(); // Eat the token.
2265
2266 if (Val == -1) {
2267 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2268 return MatchOperand_ParseFail;
2269 }
2270 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2271 getContext()),
2272 S, Parser.getTok().getLoc()));
2273 return MatchOperand_Success;
2274}
2275
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002276/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2277/// instructions. Legal values are:
2278/// lsl #n 'n' in [0,31]
2279/// asr #n 'n' in [1,32]
2280/// n == 32 encoded as n == 0.
2281ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2282parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2283 const AsmToken &Tok = Parser.getTok();
2284 SMLoc S = Tok.getLoc();
2285 if (Tok.isNot(AsmToken::Identifier)) {
2286 Error(S, "shift operator 'asr' or 'lsl' expected");
2287 return MatchOperand_ParseFail;
2288 }
2289 StringRef ShiftName = Tok.getString();
2290 bool isASR;
2291 if (ShiftName == "lsl" || ShiftName == "LSL")
2292 isASR = false;
2293 else if (ShiftName == "asr" || ShiftName == "ASR")
2294 isASR = true;
2295 else {
2296 Error(S, "shift operator 'asr' or 'lsl' expected");
2297 return MatchOperand_ParseFail;
2298 }
2299 Parser.Lex(); // Eat the operator.
2300
2301 // A '#' and a shift amount.
2302 if (Parser.getTok().isNot(AsmToken::Hash)) {
2303 Error(Parser.getTok().getLoc(), "'#' expected");
2304 return MatchOperand_ParseFail;
2305 }
2306 Parser.Lex(); // Eat hash token.
2307
2308 const MCExpr *ShiftAmount;
2309 SMLoc E = Parser.getTok().getLoc();
2310 if (getParser().ParseExpression(ShiftAmount)) {
2311 Error(E, "malformed shift expression");
2312 return MatchOperand_ParseFail;
2313 }
2314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2315 if (!CE) {
2316 Error(E, "shift amount must be an immediate");
2317 return MatchOperand_ParseFail;
2318 }
2319
2320 int64_t Val = CE->getValue();
2321 if (isASR) {
2322 // Shift amount must be in [1,32]
2323 if (Val < 1 || Val > 32) {
2324 Error(E, "'asr' shift amount must be in range [1,32]");
2325 return MatchOperand_ParseFail;
2326 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002327 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2328 if (isThumb() && Val == 32) {
2329 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2330 return MatchOperand_ParseFail;
2331 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002332 if (Val == 32) Val = 0;
2333 } else {
2334 // Shift amount must be in [1,32]
2335 if (Val < 0 || Val > 31) {
2336 Error(E, "'lsr' shift amount must be in range [0,31]");
2337 return MatchOperand_ParseFail;
2338 }
2339 }
2340
2341 E = Parser.getTok().getLoc();
2342 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2343
2344 return MatchOperand_Success;
2345}
2346
Jim Grosbach833b9d32011-07-27 20:15:40 +00002347/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2348/// of instructions. Legal values are:
2349/// ror #n 'n' in {0, 8, 16, 24}
2350ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2351parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2352 const AsmToken &Tok = Parser.getTok();
2353 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002354 if (Tok.isNot(AsmToken::Identifier))
2355 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002356 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002357 if (ShiftName != "ror" && ShiftName != "ROR")
2358 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002359 Parser.Lex(); // Eat the operator.
2360
2361 // A '#' and a rotate amount.
2362 if (Parser.getTok().isNot(AsmToken::Hash)) {
2363 Error(Parser.getTok().getLoc(), "'#' expected");
2364 return MatchOperand_ParseFail;
2365 }
2366 Parser.Lex(); // Eat hash token.
2367
2368 const MCExpr *ShiftAmount;
2369 SMLoc E = Parser.getTok().getLoc();
2370 if (getParser().ParseExpression(ShiftAmount)) {
2371 Error(E, "malformed rotate expression");
2372 return MatchOperand_ParseFail;
2373 }
2374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2375 if (!CE) {
2376 Error(E, "rotate amount must be an immediate");
2377 return MatchOperand_ParseFail;
2378 }
2379
2380 int64_t Val = CE->getValue();
2381 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2382 // normally, zero is represented in asm by omitting the rotate operand
2383 // entirely.
2384 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2385 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2386 return MatchOperand_ParseFail;
2387 }
2388
2389 E = Parser.getTok().getLoc();
2390 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2391
2392 return MatchOperand_Success;
2393}
2394
Jim Grosbach864b6092011-07-28 21:34:26 +00002395ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2396parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2397 SMLoc S = Parser.getTok().getLoc();
2398 // The bitfield descriptor is really two operands, the LSB and the width.
2399 if (Parser.getTok().isNot(AsmToken::Hash)) {
2400 Error(Parser.getTok().getLoc(), "'#' expected");
2401 return MatchOperand_ParseFail;
2402 }
2403 Parser.Lex(); // Eat hash token.
2404
2405 const MCExpr *LSBExpr;
2406 SMLoc E = Parser.getTok().getLoc();
2407 if (getParser().ParseExpression(LSBExpr)) {
2408 Error(E, "malformed immediate expression");
2409 return MatchOperand_ParseFail;
2410 }
2411 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2412 if (!CE) {
2413 Error(E, "'lsb' operand must be an immediate");
2414 return MatchOperand_ParseFail;
2415 }
2416
2417 int64_t LSB = CE->getValue();
2418 // The LSB must be in the range [0,31]
2419 if (LSB < 0 || LSB > 31) {
2420 Error(E, "'lsb' operand must be in the range [0,31]");
2421 return MatchOperand_ParseFail;
2422 }
2423 E = Parser.getTok().getLoc();
2424
2425 // Expect another immediate operand.
2426 if (Parser.getTok().isNot(AsmToken::Comma)) {
2427 Error(Parser.getTok().getLoc(), "too few operands");
2428 return MatchOperand_ParseFail;
2429 }
2430 Parser.Lex(); // Eat hash token.
2431 if (Parser.getTok().isNot(AsmToken::Hash)) {
2432 Error(Parser.getTok().getLoc(), "'#' expected");
2433 return MatchOperand_ParseFail;
2434 }
2435 Parser.Lex(); // Eat hash token.
2436
2437 const MCExpr *WidthExpr;
2438 if (getParser().ParseExpression(WidthExpr)) {
2439 Error(E, "malformed immediate expression");
2440 return MatchOperand_ParseFail;
2441 }
2442 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2443 if (!CE) {
2444 Error(E, "'width' operand must be an immediate");
2445 return MatchOperand_ParseFail;
2446 }
2447
2448 int64_t Width = CE->getValue();
2449 // The LSB must be in the range [1,32-lsb]
2450 if (Width < 1 || Width > 32 - LSB) {
2451 Error(E, "'width' operand must be in the range [1,32-lsb]");
2452 return MatchOperand_ParseFail;
2453 }
2454 E = Parser.getTok().getLoc();
2455
2456 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2457
2458 return MatchOperand_Success;
2459}
2460
Jim Grosbachd3595712011-08-03 23:50:40 +00002461ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2462parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2463 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00002464 // postidx_reg := '+' register {, shift}
2465 // | '-' register {, shift}
2466 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00002467
2468 // This method must return MatchOperand_NoMatch without consuming any tokens
2469 // in the case where there is no match, as other alternatives take other
2470 // parse methods.
2471 AsmToken Tok = Parser.getTok();
2472 SMLoc S = Tok.getLoc();
2473 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002474 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00002475 int Reg = -1;
2476 if (Tok.is(AsmToken::Plus)) {
2477 Parser.Lex(); // Eat the '+' token.
2478 haveEaten = true;
2479 } else if (Tok.is(AsmToken::Minus)) {
2480 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002481 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00002482 haveEaten = true;
2483 }
2484 if (Parser.getTok().is(AsmToken::Identifier))
2485 Reg = tryParseRegister();
2486 if (Reg == -1) {
2487 if (!haveEaten)
2488 return MatchOperand_NoMatch;
2489 Error(Parser.getTok().getLoc(), "register expected");
2490 return MatchOperand_ParseFail;
2491 }
2492 SMLoc E = Parser.getTok().getLoc();
2493
Jim Grosbachc320c852011-08-05 21:28:30 +00002494 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2495 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002496 if (Parser.getTok().is(AsmToken::Comma)) {
2497 Parser.Lex(); // Eat the ','.
2498 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2499 return MatchOperand_ParseFail;
2500 }
Jim Grosbachc320c852011-08-05 21:28:30 +00002501
2502 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2503 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00002504
2505 return MatchOperand_Success;
2506}
2507
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00002508ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2509parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2510 // Check for a post-index addressing register operand. Specifically:
2511 // am3offset := '+' register
2512 // | '-' register
2513 // | register
2514 // | # imm
2515 // | # + imm
2516 // | # - imm
2517
2518 // This method must return MatchOperand_NoMatch without consuming any tokens
2519 // in the case where there is no match, as other alternatives take other
2520 // parse methods.
2521 AsmToken Tok = Parser.getTok();
2522 SMLoc S = Tok.getLoc();
2523
2524 // Do immediates first, as we always parse those if we have a '#'.
2525 if (Parser.getTok().is(AsmToken::Hash)) {
2526 Parser.Lex(); // Eat the '#'.
2527 // Explicitly look for a '-', as we need to encode negative zero
2528 // differently.
2529 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2530 const MCExpr *Offset;
2531 if (getParser().ParseExpression(Offset))
2532 return MatchOperand_ParseFail;
2533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2534 if (!CE) {
2535 Error(S, "constant expression expected");
2536 return MatchOperand_ParseFail;
2537 }
2538 SMLoc E = Tok.getLoc();
2539 // Negative zero is encoded as the flag value INT32_MIN.
2540 int32_t Val = CE->getValue();
2541 if (isNegative && Val == 0)
2542 Val = INT32_MIN;
2543
2544 Operands.push_back(
2545 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2546
2547 return MatchOperand_Success;
2548 }
2549
2550
2551 bool haveEaten = false;
2552 bool isAdd = true;
2553 int Reg = -1;
2554 if (Tok.is(AsmToken::Plus)) {
2555 Parser.Lex(); // Eat the '+' token.
2556 haveEaten = true;
2557 } else if (Tok.is(AsmToken::Minus)) {
2558 Parser.Lex(); // Eat the '-' token.
2559 isAdd = false;
2560 haveEaten = true;
2561 }
2562 if (Parser.getTok().is(AsmToken::Identifier))
2563 Reg = tryParseRegister();
2564 if (Reg == -1) {
2565 if (!haveEaten)
2566 return MatchOperand_NoMatch;
2567 Error(Parser.getTok().getLoc(), "register expected");
2568 return MatchOperand_ParseFail;
2569 }
2570 SMLoc E = Parser.getTok().getLoc();
2571
2572 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2573 0, S, E));
2574
2575 return MatchOperand_Success;
2576}
2577
Jim Grosbach7db8d692011-09-08 22:07:06 +00002578/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2579/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2580/// when they refer multiple MIOperands inside a single one.
2581bool ARMAsmParser::
2582cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2583 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2584 // Rt, Rt2
2585 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2586 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2587 // Create a writeback register dummy placeholder.
2588 Inst.addOperand(MCOperand::CreateReg(0));
2589 // addr
2590 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2591 // pred
2592 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2593 return true;
2594}
2595
2596/// cvtT2StrdPre - Convert parsed operands to MCInst.
2597/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2598/// when they refer multiple MIOperands inside a single one.
2599bool ARMAsmParser::
2600cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2601 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2602 // Create a writeback register dummy placeholder.
2603 Inst.addOperand(MCOperand::CreateReg(0));
2604 // Rt, Rt2
2605 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2606 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2607 // addr
2608 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2609 // pred
2610 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2611 return true;
2612}
2613
Jim Grosbachc086f682011-09-08 00:39:19 +00002614/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2615/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2616/// when they refer multiple MIOperands inside a single one.
2617bool ARMAsmParser::
2618cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2619 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2620 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2621
2622 // Create a writeback register dummy placeholder.
2623 Inst.addOperand(MCOperand::CreateImm(0));
2624
2625 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2626 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2627 return true;
2628}
2629
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00002630/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2631/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2632/// when they refer multiple MIOperands inside a single one.
2633bool ARMAsmParser::
2634cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2635 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2636 // Create a writeback register dummy placeholder.
2637 Inst.addOperand(MCOperand::CreateImm(0));
2638 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2639 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2640 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2641 return true;
2642}
2643
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002644/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002645/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2646/// when they refer multiple MIOperands inside a single one.
2647bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002648cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002649 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2650 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2651
2652 // Create a writeback register dummy placeholder.
2653 Inst.addOperand(MCOperand::CreateImm(0));
2654
Jim Grosbachd3595712011-08-03 23:50:40 +00002655 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002656 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2657 return true;
2658}
2659
Owen Anderson16d33f32011-08-26 20:43:14 +00002660/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2661/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2662/// when they refer multiple MIOperands inside a single one.
2663bool ARMAsmParser::
2664cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2665 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2666 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2667
2668 // Create a writeback register dummy placeholder.
2669 Inst.addOperand(MCOperand::CreateImm(0));
2670
2671 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2672 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2673 return true;
2674}
2675
2676
Jim Grosbachd564bf32011-08-11 19:22:40 +00002677/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2678/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2679/// when they refer multiple MIOperands inside a single one.
2680bool ARMAsmParser::
2681cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2682 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2683 // Create a writeback register dummy placeholder.
2684 Inst.addOperand(MCOperand::CreateImm(0));
2685 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2686 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2687 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2688 return true;
2689}
2690
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002691/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002692/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2693/// when they refer multiple MIOperands inside a single one.
2694bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002695cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002696 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2697 // Create a writeback register dummy placeholder.
2698 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00002699 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2700 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2701 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00002702 return true;
2703}
2704
Jim Grosbachd886f8c2011-08-11 21:17:22 +00002705/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2706/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2707/// when they refer multiple MIOperands inside a single one.
2708bool ARMAsmParser::
2709cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2710 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2711 // Create a writeback register dummy placeholder.
2712 Inst.addOperand(MCOperand::CreateImm(0));
2713 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2714 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2715 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2716 return true;
2717}
2718
Jim Grosbachd3595712011-08-03 23:50:40 +00002719/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2720/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2721/// when they refer multiple MIOperands inside a single one.
2722bool ARMAsmParser::
2723cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2724 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2725 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002726 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00002727 // Create a writeback register dummy placeholder.
2728 Inst.addOperand(MCOperand::CreateImm(0));
2729 // addr
2730 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2731 // offset
2732 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2733 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2735 return true;
2736}
2737
Jim Grosbachd3595712011-08-03 23:50:40 +00002738/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2740/// when they refer multiple MIOperands inside a single one.
2741bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00002742cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2744 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00002745 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002746 // Create a writeback register dummy placeholder.
2747 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00002748 // addr
2749 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2750 // offset
2751 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2752 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002753 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2754 return true;
2755}
2756
Jim Grosbachd3595712011-08-03 23:50:40 +00002757/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002758/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2759/// when they refer multiple MIOperands inside a single one.
2760bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00002761cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2762 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002763 // Create a writeback register dummy placeholder.
2764 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00002765 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002766 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00002767 // addr
2768 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2769 // offset
2770 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2771 // pred
2772 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2773 return true;
2774}
2775
2776/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2777/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2778/// when they refer multiple MIOperands inside a single one.
2779bool ARMAsmParser::
2780cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2781 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2782 // Create a writeback register dummy placeholder.
2783 Inst.addOperand(MCOperand::CreateImm(0));
2784 // Rt
2785 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2786 // addr
2787 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2788 // offset
2789 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2790 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002791 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2792 return true;
2793}
2794
Jim Grosbach5b96b802011-08-10 20:29:19 +00002795/// cvtLdrdPre - Convert parsed operands to MCInst.
2796/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2797/// when they refer multiple MIOperands inside a single one.
2798bool ARMAsmParser::
2799cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2800 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2801 // Rt, Rt2
2802 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2803 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2804 // Create a writeback register dummy placeholder.
2805 Inst.addOperand(MCOperand::CreateImm(0));
2806 // addr
2807 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2808 // pred
2809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2810 return true;
2811}
2812
Jim Grosbacheb09f492011-08-11 20:28:23 +00002813/// cvtStrdPre - Convert parsed operands to MCInst.
2814/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2815/// when they refer multiple MIOperands inside a single one.
2816bool ARMAsmParser::
2817cvtStrdPre(MCInst &Inst, unsigned Opcode,
2818 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2819 // Create a writeback register dummy placeholder.
2820 Inst.addOperand(MCOperand::CreateImm(0));
2821 // Rt, Rt2
2822 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2823 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2824 // addr
2825 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2826 // pred
2827 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2828 return true;
2829}
2830
Jim Grosbachcd4dd252011-08-10 22:42:16 +00002831/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2832/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2833/// when they refer multiple MIOperands inside a single one.
2834bool ARMAsmParser::
2835cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2836 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2837 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2838 // Create a writeback register dummy placeholder.
2839 Inst.addOperand(MCOperand::CreateImm(0));
2840 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2841 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2842 return true;
2843}
2844
Jim Grosbach8e048492011-08-19 22:07:46 +00002845/// cvtThumbMultiple- Convert parsed operands to MCInst.
2846/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2847/// when they refer multiple MIOperands inside a single one.
2848bool ARMAsmParser::
2849cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
2850 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2851 // The second source operand must be the same register as the destination
2852 // operand.
2853 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00002854 (((ARMOperand*)Operands[3])->getReg() !=
2855 ((ARMOperand*)Operands[5])->getReg()) &&
2856 (((ARMOperand*)Operands[3])->getReg() !=
2857 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00002858 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00002859 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00002860 return false;
2861 }
2862 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2863 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
2864 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00002865 // If we have a three-operand form, use that, else the second source operand
2866 // is just the destination operand again.
2867 if (Operands.size() == 6)
2868 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
2869 else
2870 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00002871 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
2872
2873 return true;
2874}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00002875
Bill Wendlinge18980a2010-11-06 22:36:58 +00002876/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002877/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00002878bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00002879parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002880 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00002881 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002882 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002883 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00002884 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002885
Sean Callanan936b0d32010-01-19 21:44:56 +00002886 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002887 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00002888 if (BaseRegNum == -1)
2889 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002890
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00002891 // The next token must either be a comma or a closing bracket.
2892 const AsmToken &Tok = Parser.getTok();
2893 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00002894 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00002895
Jim Grosbachd3595712011-08-03 23:50:40 +00002896 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002897 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00002898 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002899
Jim Grosbachd3595712011-08-03 23:50:40 +00002900 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
2901 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00002902
Jim Grosbach40700e02011-09-19 18:42:21 +00002903 // If there's a pre-indexing writeback marker, '!', just add it as a token
2904 // operand. It's rather odd, but syntactically valid.
2905 if (Parser.getTok().is(AsmToken::Exclaim)) {
2906 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2907 Parser.Lex(); // Eat the '!'.
2908 }
2909
Jim Grosbachd3595712011-08-03 23:50:40 +00002910 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002911 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00002912
Jim Grosbachd3595712011-08-03 23:50:40 +00002913 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
2914 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00002915
Jim Grosbachd3595712011-08-03 23:50:40 +00002916 // If we have a '#' it's an immediate offset, else assume it's a register
2917 // offset.
2918 if (Parser.getTok().is(AsmToken::Hash)) {
2919 Parser.Lex(); // Eat the '#'.
2920 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00002921
Owen Anderson967674d2011-08-29 19:36:44 +00002922 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00002923 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002924 if (getParser().ParseExpression(Offset))
2925 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00002926
2927 // The expression has to be a constant. Memory references with relocations
2928 // don't come through here, as they use the <label> forms of the relevant
2929 // instructions.
2930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2931 if (!CE)
2932 return Error (E, "constant expression expected");
2933
Owen Anderson967674d2011-08-29 19:36:44 +00002934 // If the constant was #-0, represent it as INT32_MIN.
2935 int32_t Val = CE->getValue();
2936 if (isNegative && Val == 0)
2937 CE = MCConstantExpr::Create(INT32_MIN, getContext());
2938
Jim Grosbachd3595712011-08-03 23:50:40 +00002939 // Now we should have the closing ']'
2940 E = Parser.getTok().getLoc();
2941 if (Parser.getTok().isNot(AsmToken::RBrac))
2942 return Error(E, "']' expected");
2943 Parser.Lex(); // Eat right bracket token.
2944
2945 // Don't worry about range checking the value here. That's handled by
2946 // the is*() predicates.
2947 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
2948 ARM_AM::no_shift, 0, false, S,E));
2949
2950 // If there's a pre-indexing writeback marker, '!', just add it as a token
2951 // operand.
2952 if (Parser.getTok().is(AsmToken::Exclaim)) {
2953 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2954 Parser.Lex(); // Eat the '!'.
2955 }
2956
2957 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002958 }
Jim Grosbachd3595712011-08-03 23:50:40 +00002959
2960 // The register offset is optionally preceded by a '+' or '-'
2961 bool isNegative = false;
2962 if (Parser.getTok().is(AsmToken::Minus)) {
2963 isNegative = true;
2964 Parser.Lex(); // Eat the '-'.
2965 } else if (Parser.getTok().is(AsmToken::Plus)) {
2966 // Nothing to do.
2967 Parser.Lex(); // Eat the '+'.
2968 }
2969
2970 E = Parser.getTok().getLoc();
2971 int OffsetRegNum = tryParseRegister();
2972 if (OffsetRegNum == -1)
2973 return Error(E, "register expected");
2974
2975 // If there's a shift operator, handle it.
2976 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002977 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00002978 if (Parser.getTok().is(AsmToken::Comma)) {
2979 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002980 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00002981 return true;
2982 }
2983
2984 // Now we should have the closing ']'
2985 E = Parser.getTok().getLoc();
2986 if (Parser.getTok().isNot(AsmToken::RBrac))
2987 return Error(E, "']' expected");
2988 Parser.Lex(); // Eat right bracket token.
2989
2990 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002991 ShiftType, ShiftImm, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00002992 S, E));
2993
Jim Grosbachc320c852011-08-05 21:28:30 +00002994 // If there's a pre-indexing writeback marker, '!', just add it as a token
2995 // operand.
2996 if (Parser.getTok().is(AsmToken::Exclaim)) {
2997 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2998 Parser.Lex(); // Eat the '!'.
2999 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003000
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003001 return false;
3002}
3003
Jim Grosbachd3595712011-08-03 23:50:40 +00003004/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003005/// ( lsl | lsr | asr | ror ) , # shift_amount
3006/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003007/// return true if it parses a shift otherwise it returns false.
3008bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3009 unsigned &Amount) {
3010 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003011 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003012 if (Tok.isNot(AsmToken::Identifier))
3013 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003014 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003015 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003016 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003017 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003018 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003019 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003020 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003021 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003022 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003023 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003024 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003025 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003026 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003027 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003028
Jim Grosbachd3595712011-08-03 23:50:40 +00003029 // rrx stands alone.
3030 Amount = 0;
3031 if (St != ARM_AM::rrx) {
3032 Loc = Parser.getTok().getLoc();
3033 // A '#' and a shift amount.
3034 const AsmToken &HashTok = Parser.getTok();
3035 if (HashTok.isNot(AsmToken::Hash))
3036 return Error(HashTok.getLoc(), "'#' expected");
3037 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003038
Jim Grosbachd3595712011-08-03 23:50:40 +00003039 const MCExpr *Expr;
3040 if (getParser().ParseExpression(Expr))
3041 return true;
3042 // Range check the immediate.
3043 // lsl, ror: 0 <= imm <= 31
3044 // lsr, asr: 0 <= imm <= 32
3045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3046 if (!CE)
3047 return Error(Loc, "shift amount must be an immediate");
3048 int64_t Imm = CE->getValue();
3049 if (Imm < 0 ||
3050 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3051 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3052 return Error(Loc, "immediate shift value out of range");
3053 Amount = Imm;
3054 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003055
3056 return false;
3057}
3058
Jim Grosbache7fbce72011-10-03 23:38:36 +00003059/// parseFPImm - A floating point immediate expression operand.
3060ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3061parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3062 SMLoc S = Parser.getTok().getLoc();
3063
3064 if (Parser.getTok().isNot(AsmToken::Hash))
3065 return MatchOperand_NoMatch;
3066 Parser.Lex(); // Eat the '#'.
3067
3068 // Handle negation, as that still comes through as a separate token.
3069 bool isNegative = false;
3070 if (Parser.getTok().is(AsmToken::Minus)) {
3071 isNegative = true;
3072 Parser.Lex();
3073 }
3074 const AsmToken &Tok = Parser.getTok();
3075 if (Tok.is(AsmToken::Real)) {
3076 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3077 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3078 // If we had a '-' in front, toggle the sign bit.
3079 IntVal ^= (uint64_t)isNegative << 63;
3080 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3081 Parser.Lex(); // Eat the token.
3082 if (Val == -1) {
3083 TokError("floating point value out of range");
3084 return MatchOperand_ParseFail;
3085 }
3086 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3087 return MatchOperand_Success;
3088 }
3089 if (Tok.is(AsmToken::Integer)) {
3090 int64_t Val = Tok.getIntVal();
3091 Parser.Lex(); // Eat the token.
3092 if (Val > 255 || Val < 0) {
3093 TokError("encoded floating point value out of range");
3094 return MatchOperand_ParseFail;
3095 }
3096 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3097 return MatchOperand_Success;
3098 }
3099
3100 TokError("invalid floating point immediate");
3101 return MatchOperand_ParseFail;
3102}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003103/// Parse a arm instruction operand. For now this parses the operand regardless
3104/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003105bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003106 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003107 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003108
3109 // Check if the current operand has a custom associated parser, if so, try to
3110 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003111 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3112 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003113 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003114 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3115 // there was a match, but an error occurred, in which case, just return that
3116 // the operand parsing failed.
3117 if (ResTy == MatchOperand_ParseFail)
3118 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003119
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003120 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003121 default:
3122 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003123 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003124 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003125 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003126 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003127 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003128 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003129 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003130 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003131 else if (Res == -1) // irrecoverable error
3132 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003133 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3134 S = Parser.getTok().getLoc();
3135 Parser.Lex();
3136 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3137 return false;
3138 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003139
3140 // Fall though for the Identifier case that is not a register or a
3141 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003142 }
Kevin Enderbyb084be92011-01-13 20:32:36 +00003143 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3144 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003145 // This was not a register so parse other operands that start with an
3146 // identifier (like labels) as expressions and create them as immediates.
3147 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003148 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003149 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003150 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003151 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003152 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3153 return false;
3154 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003155 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003156 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003157 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003158 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003159 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003160 // #42 -> immediate.
3161 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003162 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003163 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003164 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003165 const MCExpr *ImmVal;
3166 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003167 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003168 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3169 if (!CE) {
3170 Error(S, "constant expression expected");
3171 return MatchOperand_ParseFail;
3172 }
3173 int32_t Val = CE->getValue();
3174 if (isNegative && Val == 0)
3175 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003176 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003177 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3178 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003179 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003180 case AsmToken::Colon: {
3181 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003182 // FIXME: Check it's an expression prefix,
3183 // e.g. (FOO - :lower16:BAR) isn't legal.
3184 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003185 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003186 return true;
3187
Evan Cheng965b3c72011-01-13 07:58:56 +00003188 const MCExpr *SubExprVal;
3189 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003190 return true;
3191
Evan Cheng965b3c72011-01-13 07:58:56 +00003192 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3193 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003194 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003195 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003196 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003197 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003198 }
3199}
3200
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003201// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003202// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003203bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003204 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003205
3206 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003207 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003208 Parser.Lex(); // Eat ':'
3209
3210 if (getLexer().isNot(AsmToken::Identifier)) {
3211 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3212 return true;
3213 }
3214
3215 StringRef IDVal = Parser.getTok().getIdentifier();
3216 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003217 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003218 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003219 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003220 } else {
3221 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3222 return true;
3223 }
3224 Parser.Lex();
3225
3226 if (getLexer().isNot(AsmToken::Colon)) {
3227 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3228 return true;
3229 }
3230 Parser.Lex(); // Eat the last ':'
3231 return false;
3232}
3233
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003234/// \brief Given a mnemonic, split out possible predication code and carry
3235/// setting letters to form a canonical mnemonic and flags.
3236//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003237// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003238// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003239StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003240 unsigned &PredicationCode,
3241 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003242 unsigned &ProcessorIMod,
3243 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003244 PredicationCode = ARMCC::AL;
3245 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003246 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003247
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003248 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003249 //
3250 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003251 if ((Mnemonic == "movs" && isThumb()) ||
3252 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3253 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3254 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3255 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3256 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3257 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3258 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003259 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003260
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003261 // First, split out any predication code. Ignore mnemonics we know aren't
3262 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003263 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003264 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003265 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003266 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003267 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3268 .Case("eq", ARMCC::EQ)
3269 .Case("ne", ARMCC::NE)
3270 .Case("hs", ARMCC::HS)
3271 .Case("cs", ARMCC::HS)
3272 .Case("lo", ARMCC::LO)
3273 .Case("cc", ARMCC::LO)
3274 .Case("mi", ARMCC::MI)
3275 .Case("pl", ARMCC::PL)
3276 .Case("vs", ARMCC::VS)
3277 .Case("vc", ARMCC::VC)
3278 .Case("hi", ARMCC::HI)
3279 .Case("ls", ARMCC::LS)
3280 .Case("ge", ARMCC::GE)
3281 .Case("lt", ARMCC::LT)
3282 .Case("gt", ARMCC::GT)
3283 .Case("le", ARMCC::LE)
3284 .Case("al", ARMCC::AL)
3285 .Default(~0U);
3286 if (CC != ~0U) {
3287 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3288 PredicationCode = CC;
3289 }
Bill Wendling193961b2010-10-29 23:50:21 +00003290 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003291
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003292 // Next, determine if we have a carry setting bit. We explicitly ignore all
3293 // the instructions we know end in 's'.
3294 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003295 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003296 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3297 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3298 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003299 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3300 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003301 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3302 CarrySetting = true;
3303 }
3304
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003305 // The "cps" instruction can have a interrupt mode operand which is glued into
3306 // the mnemonic. Check if this is the case, split it and parse the imod op
3307 if (Mnemonic.startswith("cps")) {
3308 // Split out any imod code.
3309 unsigned IMod =
3310 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3311 .Case("ie", ARM_PROC::IE)
3312 .Case("id", ARM_PROC::ID)
3313 .Default(~0U);
3314 if (IMod != ~0U) {
3315 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3316 ProcessorIMod = IMod;
3317 }
3318 }
3319
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003320 // The "it" instruction has the condition mask on the end of the mnemonic.
3321 if (Mnemonic.startswith("it")) {
3322 ITMask = Mnemonic.slice(2, Mnemonic.size());
3323 Mnemonic = Mnemonic.slice(0, 2);
3324 }
3325
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003326 return Mnemonic;
3327}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003328
3329/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3330/// inclusion of carry set or predication code operands.
3331//
3332// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003333void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003334getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003335 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003336 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3337 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003338 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003339 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003340 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003341 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003342 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003343 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003344 Mnemonic == "mla" || Mnemonic == "smlal" ||
3345 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003346 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003347 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00003348 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003349
Daniel Dunbar09264122011-01-11 19:06:29 +00003350 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3351 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3352 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3353 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00003354 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3355 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00003356 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00003357 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
3358 !isThumb()) ||
3359 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3360 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003361 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003362 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003363 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003364 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003365
Jim Grosbach6c45b752011-09-16 16:39:25 +00003366 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003367 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00003368 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003369 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003370 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003371}
3372
Jim Grosbach7283da92011-08-16 21:12:37 +00003373bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3374 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003375 // FIXME: This is all horribly hacky. We really need a better way to deal
3376 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00003377
3378 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3379 // another does not. Specifically, the MOVW instruction does not. So we
3380 // special case it here and remove the defaulted (non-setting) cc_out
3381 // operand if that's the instruction we're trying to match.
3382 //
3383 // We do this as post-processing of the explicit operands rather than just
3384 // conditionally adding the cc_out in the first place because we need
3385 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00003386 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00003387 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3388 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3389 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3390 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003391
3392 // Register-register 'add' for thumb does not have a cc_out operand
3393 // when there are only two register operands.
3394 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3395 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3396 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3397 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3398 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003399 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003400 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3401 // have to check the immediate range here since Thumb2 has a variant
3402 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003403 if (((isThumb() && Mnemonic == "add") ||
3404 (isThumbTwo() && Mnemonic == "sub")) &&
3405 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003406 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3407 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3408 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003409 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3410 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3411 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003412 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003413 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3414 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003415 // selecting via the generic "add" mnemonic, so to know that we
3416 // should remove the cc_out operand, we have to explicitly check that
3417 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003418 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3419 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003420 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3421 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3422 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3423 // Nest conditions rather than one big 'if' statement for readability.
3424 //
3425 // If either register is a high reg, it's either one of the SP
3426 // variants (handled above) or a 32-bit encoding, so we just
3427 // check against T3.
3428 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3429 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3430 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3431 return false;
3432 // If both registers are low, we're in an IT block, and the immediate is
3433 // in range, we should use encoding T1 instead, which has a cc_out.
3434 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003435 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003436 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3437 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3438 return false;
3439
3440 // Otherwise, we use encoding T4, which does not have a cc_out
3441 // operand.
3442 return true;
3443 }
3444
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003445 // The thumb2 multiply instruction doesn't have a CCOut register, so
3446 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3447 // use the 16-bit encoding or not.
3448 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3449 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3450 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3451 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3452 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3453 // If the registers aren't low regs, the destination reg isn't the
3454 // same as one of the source regs, or the cc_out operand is zero
3455 // outside of an IT block, we have to use the 32-bit encoding, so
3456 // remove the cc_out operand.
3457 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3458 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3459 !inITBlock() ||
3460 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3461 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3462 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3463 static_cast<ARMOperand*>(Operands[4])->getReg())))
3464 return true;
3465
3466
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003467
Jim Grosbach4b701af2011-08-24 21:42:27 +00003468 // Register-register 'add/sub' for thumb does not have a cc_out operand
3469 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3470 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3471 // right, this will result in better diagnostics (which operand is off)
3472 // anyway.
3473 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3474 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003475 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3476 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3477 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3478 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003479
Jim Grosbach7283da92011-08-16 21:12:37 +00003480 return false;
3481}
3482
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003483/// Parse an arm instruction mnemonic followed by its operands.
3484bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3485 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3486 // Create the leading tokens for the mnemonic, split by '.' characters.
3487 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003488 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003489
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003490 // Split out the predication code and carry setting flag from the mnemonic.
3491 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003492 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003493 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003494 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003495 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003496 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003497
Jim Grosbach1c171b12011-08-25 17:23:55 +00003498 // In Thumb1, only the branch (B) instruction can be predicated.
3499 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3500 Parser.EatToEndOfStatement();
3501 return Error(NameLoc, "conditional execution not supported in Thumb1");
3502 }
3503
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003504 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3505
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003506 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3507 // is the mask as it will be for the IT encoding if the conditional
3508 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3509 // where the conditional bit0 is zero, the instruction post-processing
3510 // will adjust the mask accordingly.
3511 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00003512 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3513 if (ITMask.size() > 3) {
3514 Parser.EatToEndOfStatement();
3515 return Error(Loc, "too many conditions on IT instruction");
3516 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003517 unsigned Mask = 8;
3518 for (unsigned i = ITMask.size(); i != 0; --i) {
3519 char pos = ITMask[i - 1];
3520 if (pos != 't' && pos != 'e') {
3521 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00003522 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003523 }
3524 Mask >>= 1;
3525 if (ITMask[i - 1] == 't')
3526 Mask |= 8;
3527 }
Jim Grosbached16ec42011-08-29 22:24:09 +00003528 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003529 }
3530
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003531 // FIXME: This is all a pretty gross hack. We should automatically handle
3532 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00003533
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003534 // Next, add the CCOut and ConditionCode operands, if needed.
3535 //
3536 // For mnemonics which can ever incorporate a carry setting bit or predication
3537 // code, our matching model involves us always generating CCOut and
3538 // ConditionCode operands to match the mnemonic "as written" and then we let
3539 // the matcher deal with finding the right instruction or generating an
3540 // appropriate error.
3541 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003542 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003543
Jim Grosbach03a8a162011-07-14 22:04:21 +00003544 // If we had a carry-set on an instruction that can't do that, issue an
3545 // error.
3546 if (!CanAcceptCarrySet && CarrySetting) {
3547 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003548 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00003549 "' can not set flags, but 's' suffix specified");
3550 }
Jim Grosbach0a547702011-07-22 17:44:50 +00003551 // If we had a predication code on an instruction that can't do that, issue an
3552 // error.
3553 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3554 Parser.EatToEndOfStatement();
3555 return Error(NameLoc, "instruction '" + Mnemonic +
3556 "' is not predicable, but condition code specified");
3557 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00003558
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003559 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00003560 if (CanAcceptCarrySet) {
3561 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003562 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00003563 Loc));
3564 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003565
3566 // Add the predication code operand, if necessary.
3567 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003568 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3569 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003570 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00003571 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003572 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003573
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003574 // Add the processor imod operand, if necessary.
3575 if (ProcessorIMod) {
3576 Operands.push_back(ARMOperand::CreateImm(
3577 MCConstantExpr::Create(ProcessorIMod, getContext()),
3578 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003579 }
3580
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003581 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003582 while (Next != StringRef::npos) {
3583 Start = Next;
3584 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003585 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003586
Jim Grosbach838ed3a2011-08-24 22:19:48 +00003587 // For now, we're only parsing Thumb1 (for the most part), so
3588 // just ignore ".n" qualifiers. We'll use them to restrict
3589 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00003590 if (ExtraToken != ".n") {
3591 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3592 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3593 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003594 }
3595
3596 // Read the remaining operands.
3597 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003598 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003599 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003600 Parser.EatToEndOfStatement();
3601 return true;
3602 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003603
3604 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00003605 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003606
3607 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003608 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003609 Parser.EatToEndOfStatement();
3610 return true;
3611 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003612 }
3613 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00003614
Chris Lattnera2a9d162010-09-11 16:18:25 +00003615 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3616 Parser.EatToEndOfStatement();
Chris Lattner91689c12010-09-08 05:10:46 +00003617 return TokError("unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00003618 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003619
Chris Lattner91689c12010-09-08 05:10:46 +00003620 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003621
Jim Grosbach7283da92011-08-16 21:12:37 +00003622 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3623 // do and don't have a cc_out optional-def operand. With some spot-checks
3624 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003625 // parse and adjust accordingly before actually matching. We shouldn't ever
3626 // try to remove a cc_out operand that was explicitly set on the the
3627 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3628 // table driven matcher doesn't fit well with the ARM instruction set.
3629 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003630 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3631 Operands.erase(Operands.begin() + 1);
3632 delete Op;
3633 }
3634
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00003635 // ARM mode 'blx' need special handling, as the register operand version
3636 // is predicable, but the label operand version is not. So, we can't rely
3637 // on the Mnemonic based checking to correctly figure out when to put
3638 // a CondCode operand in the list. If we're trying to match the label
3639 // version, remove the CondCode operand here.
3640 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3641 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3642 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3643 Operands.erase(Operands.begin() + 1);
3644 delete Op;
3645 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00003646
3647 // The vector-compare-to-zero instructions have a literal token "#0" at
3648 // the end that comes to here as an immediate operand. Convert it to a
3649 // token to play nicely with the matcher.
3650 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3651 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3652 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3653 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3655 if (CE && CE->getValue() == 0) {
3656 Operands.erase(Operands.begin() + 5);
3657 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3658 delete Op;
3659 }
3660 }
Jim Grosbach46b66462011-10-03 22:30:24 +00003661 // VCMP{E} does the same thing, but with a different operand count.
3662 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3663 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3664 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3666 if (CE && CE->getValue() == 0) {
3667 Operands.erase(Operands.begin() + 4);
3668 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3669 delete Op;
3670 }
3671 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00003672 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3673 // end. Convert it to a token here.
3674 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3675 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3676 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3678 if (CE && CE->getValue() == 0) {
3679 Operands.erase(Operands.begin() + 5);
3680 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3681 delete Op;
3682 }
3683 }
3684
Chris Lattnerf29c0b62010-01-14 22:21:20 +00003685 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00003686}
3687
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003688// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00003689
3690// return 'true' if register list contains non-low GPR registers,
3691// 'false' otherwise. If Reg is in the register list or is HiReg, set
3692// 'containsReg' to true.
3693static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3694 unsigned HiReg, bool &containsReg) {
3695 containsReg = false;
3696 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3697 unsigned OpReg = Inst.getOperand(i).getReg();
3698 if (OpReg == Reg)
3699 containsReg = true;
3700 // Anything other than a low register isn't legal here.
3701 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3702 return true;
3703 }
3704 return false;
3705}
3706
Jim Grosbacha31f2232011-09-07 18:05:34 +00003707// Check if the specified regisgter is in the register list of the inst,
3708// starting at the indicated operand number.
3709static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3710 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3711 unsigned OpReg = Inst.getOperand(i).getReg();
3712 if (OpReg == Reg)
3713 return true;
3714 }
3715 return false;
3716}
3717
Jim Grosbached16ec42011-08-29 22:24:09 +00003718// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3719// the ARMInsts array) instead. Getting that here requires awkward
3720// API changes, though. Better way?
3721namespace llvm {
3722extern MCInstrDesc ARMInsts[];
3723}
3724static MCInstrDesc &getInstDesc(unsigned Opcode) {
3725 return ARMInsts[Opcode];
3726}
3727
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003728// FIXME: We would really like to be able to tablegen'erate this.
3729bool ARMAsmParser::
3730validateInstruction(MCInst &Inst,
3731 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003732 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3733 SMLoc Loc = Operands[0]->getStartLoc();
3734 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00003735 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3736 // being allowed in IT blocks, but not being predicable. It just always
3737 // executes.
3738 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003739 unsigned bit = 1;
3740 if (ITState.FirstCond)
3741 ITState.FirstCond = false;
3742 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00003743 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00003744 // The instruction must be predicable.
3745 if (!MCID.isPredicable())
3746 return Error(Loc, "instructions in IT block must be predicable");
3747 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3748 unsigned ITCond = bit ? ITState.Cond :
3749 ARMCC::getOppositeCondition(ITState.Cond);
3750 if (Cond != ITCond) {
3751 // Find the condition code Operand to get its SMLoc information.
3752 SMLoc CondLoc;
3753 for (unsigned i = 1; i < Operands.size(); ++i)
3754 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3755 CondLoc = Operands[i]->getStartLoc();
3756 return Error(CondLoc, "incorrect condition in IT block; got '" +
3757 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3758 "', but expected '" +
3759 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3760 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00003761 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00003762 } else if (isThumbTwo() && MCID.isPredicable() &&
3763 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00003764 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3765 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00003766 return Error(Loc, "predicated instructions must be in IT block");
3767
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003768 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00003769 case ARM::LDRD:
3770 case ARM::LDRD_PRE:
3771 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003772 case ARM::LDREXD: {
3773 // Rt2 must be Rt + 1.
3774 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3775 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3776 if (Rt2 != Rt + 1)
3777 return Error(Operands[3]->getStartLoc(),
3778 "destination operands must be sequential");
3779 return false;
3780 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00003781 case ARM::STRD: {
3782 // Rt2 must be Rt + 1.
3783 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3784 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3785 if (Rt2 != Rt + 1)
3786 return Error(Operands[3]->getStartLoc(),
3787 "source operands must be sequential");
3788 return false;
3789 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00003790 case ARM::STRD_PRE:
3791 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003792 case ARM::STREXD: {
3793 // Rt2 must be Rt + 1.
3794 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3795 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
3796 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00003797 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003798 "source operands must be sequential");
3799 return false;
3800 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00003801 case ARM::SBFX:
3802 case ARM::UBFX: {
3803 // width must be in range [1, 32-lsb]
3804 unsigned lsb = Inst.getOperand(2).getImm();
3805 unsigned widthm1 = Inst.getOperand(3).getImm();
3806 if (widthm1 >= 32 - lsb)
3807 return Error(Operands[5]->getStartLoc(),
3808 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00003809 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00003810 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00003811 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00003812 // If we're parsing Thumb2, the .w variant is available and handles
3813 // most cases that are normally illegal for a Thumb1 LDM
3814 // instruction. We'll make the transformation in processInstruction()
3815 // if necessary.
3816 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00003817 // Thumb LDM instructions are writeback iff the base register is not
3818 // in the register list.
3819 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00003820 bool hasWritebackToken =
3821 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3822 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00003823 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00003824 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00003825 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
3826 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00003827 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00003828 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00003829 return Error(Operands[2]->getStartLoc(),
3830 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00003831 // If we should not have writeback, there must not be a '!'. This is
3832 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00003833 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00003834 return Error(Operands[3]->getStartLoc(),
3835 "writeback operator '!' not allowed when base register "
3836 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00003837
3838 break;
3839 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00003840 case ARM::t2LDMIA_UPD: {
3841 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
3842 return Error(Operands[4]->getStartLoc(),
3843 "writeback operator '!' not allowed when base register "
3844 "in register list");
3845 break;
3846 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003847 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00003848 bool listContainsBase;
3849 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
3850 return Error(Operands[2]->getStartLoc(),
3851 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003852 break;
3853 }
3854 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00003855 bool listContainsBase;
3856 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
3857 return Error(Operands[2]->getStartLoc(),
3858 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00003859 break;
3860 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00003861 case ARM::tSTMIA_UPD: {
3862 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00003863 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00003864 return Error(Operands[4]->getStartLoc(),
3865 "registers must be in range r0-r7");
3866 break;
3867 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00003868 }
3869
3870 return false;
3871}
3872
Jim Grosbach8ba76c62011-08-11 17:35:48 +00003873void ARMAsmParser::
3874processInstruction(MCInst &Inst,
3875 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3876 switch (Inst.getOpcode()) {
3877 case ARM::LDMIA_UPD:
3878 // If this is a load of a single register via a 'pop', then we should use
3879 // a post-indexed LDR instruction instead, per the ARM ARM.
3880 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
3881 Inst.getNumOperands() == 5) {
3882 MCInst TmpInst;
3883 TmpInst.setOpcode(ARM::LDR_POST_IMM);
3884 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3885 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3886 TmpInst.addOperand(Inst.getOperand(1)); // Rn
3887 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
3888 TmpInst.addOperand(MCOperand::CreateImm(4));
3889 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3890 TmpInst.addOperand(Inst.getOperand(3));
3891 Inst = TmpInst;
3892 }
3893 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00003894 case ARM::STMDB_UPD:
3895 // If this is a store of a single register via a 'push', then we should use
3896 // a pre-indexed STR instruction instead, per the ARM ARM.
3897 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
3898 Inst.getNumOperands() == 5) {
3899 MCInst TmpInst;
3900 TmpInst.setOpcode(ARM::STR_PRE_IMM);
3901 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3902 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3903 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
3904 TmpInst.addOperand(MCOperand::CreateImm(-4));
3905 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3906 TmpInst.addOperand(Inst.getOperand(3));
3907 Inst = TmpInst;
3908 }
3909 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00003910 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00003911 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3912 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3913 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3914 // to encoding T1 if <Rd> is omitted."
3915 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00003916 Inst.setOpcode(ARM::tADDi3);
3917 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003918 case ARM::tSUBi8:
3919 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3920 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3921 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3922 // to encoding T1 if <Rd> is omitted."
3923 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
3924 Inst.setOpcode(ARM::tSUBi3);
3925 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00003926 case ARM::tB:
3927 // A Thumb conditional branch outside of an IT block is a tBcc.
3928 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3929 Inst.setOpcode(ARM::tBcc);
3930 break;
3931 case ARM::t2B:
3932 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
3933 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3934 Inst.setOpcode(ARM::t2Bcc);
3935 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00003936 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00003937 // If the conditional is AL or we're in an IT block, we really want t2B.
3938 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00003939 Inst.setOpcode(ARM::t2B);
3940 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00003941 case ARM::tBcc:
3942 // If the conditional is AL, we really want tB.
3943 if (Inst.getOperand(1).getImm() == ARMCC::AL)
3944 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00003945 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00003946 case ARM::tLDMIA: {
3947 // If the register list contains any high registers, or if the writeback
3948 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
3949 // instead if we're in Thumb2. Otherwise, this should have generated
3950 // an error in validateInstruction().
3951 unsigned Rn = Inst.getOperand(0).getReg();
3952 bool hasWritebackToken =
3953 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3954 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
3955 bool listContainsBase;
3956 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
3957 (!listContainsBase && !hasWritebackToken) ||
3958 (listContainsBase && hasWritebackToken)) {
3959 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3960 assert (isThumbTwo());
3961 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
3962 // If we're switching to the updating version, we need to insert
3963 // the writeback tied operand.
3964 if (hasWritebackToken)
3965 Inst.insert(Inst.begin(),
3966 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
3967 }
3968 break;
3969 }
Jim Grosbach099c9762011-09-16 20:50:13 +00003970 case ARM::tSTMIA_UPD: {
3971 // If the register list contains any high registers, we need to use
3972 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
3973 // should have generated an error in validateInstruction().
3974 unsigned Rn = Inst.getOperand(0).getReg();
3975 bool listContainsBase;
3976 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
3977 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3978 assert (isThumbTwo());
3979 Inst.setOpcode(ARM::t2STMIA_UPD);
3980 }
3981 break;
3982 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003983 case ARM::t2MOVi: {
3984 // If we can use the 16-bit encoding and the user didn't explicitly
3985 // request the 32-bit variant, transform it here.
3986 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
3987 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00003988 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
3989 Inst.getOperand(4).getReg() == ARM::CPSR) ||
3990 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003991 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
3992 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
3993 // The operands aren't in the same order for tMOVi8...
3994 MCInst TmpInst;
3995 TmpInst.setOpcode(ARM::tMOVi8);
3996 TmpInst.addOperand(Inst.getOperand(0));
3997 TmpInst.addOperand(Inst.getOperand(4));
3998 TmpInst.addOperand(Inst.getOperand(1));
3999 TmpInst.addOperand(Inst.getOperand(2));
4000 TmpInst.addOperand(Inst.getOperand(3));
4001 Inst = TmpInst;
4002 }
4003 break;
4004 }
4005 case ARM::t2MOVr: {
4006 // If we can use the 16-bit encoding and the user didn't explicitly
4007 // request the 32-bit variant, transform it here.
4008 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4009 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4010 Inst.getOperand(2).getImm() == ARMCC::AL &&
4011 Inst.getOperand(4).getReg() == ARM::CPSR &&
4012 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4013 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4014 // The operands aren't the same for tMOV[S]r... (no cc_out)
4015 MCInst TmpInst;
4016 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4017 TmpInst.addOperand(Inst.getOperand(0));
4018 TmpInst.addOperand(Inst.getOperand(1));
4019 TmpInst.addOperand(Inst.getOperand(2));
4020 TmpInst.addOperand(Inst.getOperand(3));
4021 Inst = TmpInst;
4022 }
4023 break;
4024 }
Jim Grosbach82213192011-09-19 20:29:33 +00004025 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004026 case ARM::t2SXTB:
4027 case ARM::t2UXTH:
4028 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004029 // If we can use the 16-bit encoding and the user didn't explicitly
4030 // request the 32-bit variant, transform it here.
4031 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4032 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4033 Inst.getOperand(2).getImm() == 0 &&
4034 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4035 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004036 unsigned NewOpc;
4037 switch (Inst.getOpcode()) {
4038 default: llvm_unreachable("Illegal opcode!");
4039 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4040 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4041 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4042 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4043 }
Jim Grosbach82213192011-09-19 20:29:33 +00004044 // The operands aren't the same for thumb1 (no rotate operand).
4045 MCInst TmpInst;
4046 TmpInst.setOpcode(NewOpc);
4047 TmpInst.addOperand(Inst.getOperand(0));
4048 TmpInst.addOperand(Inst.getOperand(1));
4049 TmpInst.addOperand(Inst.getOperand(3));
4050 TmpInst.addOperand(Inst.getOperand(4));
4051 Inst = TmpInst;
4052 }
4053 break;
4054 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004055 case ARM::t2IT: {
4056 // The mask bits for all but the first condition are represented as
4057 // the low bit of the condition code value implies 't'. We currently
4058 // always have 1 implies 't', so XOR toggle the bits if the low bit
4059 // of the condition code is zero. The encoding also expects the low
4060 // bit of the condition to be encoded as bit 4 of the mask operand,
4061 // so mask that in if needed
4062 MCOperand &MO = Inst.getOperand(1);
4063 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004064 unsigned OrigMask = Mask;
4065 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004066 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004067 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4068 for (unsigned i = 3; i != TZ; --i)
4069 Mask ^= 1 << i;
4070 } else
4071 Mask |= 0x10;
4072 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004073
4074 // Set up the IT block state according to the IT instruction we just
4075 // matched.
4076 assert(!inITBlock() && "nested IT blocks?!");
4077 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4078 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4079 ITState.CurPosition = 0;
4080 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004081 break;
4082 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004083 }
4084}
4085
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004086unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4087 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4088 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004089 unsigned Opc = Inst.getOpcode();
4090 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004091 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4092 assert(MCID.hasOptionalDef() &&
4093 "optionally flag setting instruction missing optional def operand");
4094 assert(MCID.NumOperands == Inst.getNumOperands() &&
4095 "operand count mismatch!");
4096 // Find the optional-def operand (cc_out).
4097 unsigned OpNo;
4098 for (OpNo = 0;
4099 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4100 ++OpNo)
4101 ;
4102 // If we're parsing Thumb1, reject it completely.
4103 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4104 return Match_MnemonicFail;
4105 // If we're parsing Thumb2, which form is legal depends on whether we're
4106 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004107 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4108 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004109 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004110 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4111 inITBlock())
4112 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004113 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004114 // Some high-register supporting Thumb1 encodings only allow both registers
4115 // to be from r0-r7 when in Thumb2.
4116 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4117 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4118 isARMLowRegister(Inst.getOperand(2).getReg()))
4119 return Match_RequiresThumb2;
4120 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004121 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004122 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4123 isARMLowRegister(Inst.getOperand(1).getReg()))
4124 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004125 return Match_Success;
4126}
4127
Chris Lattner9487de62010-10-28 21:28:01 +00004128bool ARMAsmParser::
4129MatchAndEmitInstruction(SMLoc IDLoc,
4130 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4131 MCStreamer &Out) {
4132 MCInst Inst;
4133 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004134 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004135 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004136 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004137 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004138 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004139 // Context sensitive operand constraints aren't handled by the matcher,
4140 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004141 if (validateInstruction(Inst, Operands)) {
4142 // Still progress the IT block, otherwise one wrong condition causes
4143 // nasty cascading errors.
4144 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004145 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004146 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004147
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004148 // Some instructions need post-processing to, for example, tweak which
4149 // encoding is selected.
4150 processInstruction(Inst, Operands);
4151
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004152 // Only move forward at the very end so that everything in validate
4153 // and process gets a consistent answer about whether we're in an IT
4154 // block.
4155 forwardITPosition();
4156
Chris Lattner9487de62010-10-28 21:28:01 +00004157 Out.EmitInstruction(Inst);
4158 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004159 case Match_MissingFeature:
4160 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4161 return true;
4162 case Match_InvalidOperand: {
4163 SMLoc ErrorLoc = IDLoc;
4164 if (ErrorInfo != ~0U) {
4165 if (ErrorInfo >= Operands.size())
4166 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004167
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004168 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4169 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4170 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004171
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004172 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004173 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004174 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004175 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004176 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004177 // The converter function will have already emited a diagnostic.
4178 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004179 case Match_RequiresNotITBlock:
4180 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004181 case Match_RequiresITBlock:
4182 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004183 case Match_RequiresV6:
4184 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4185 case Match_RequiresThumb2:
4186 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004187 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004188
Eric Christopher91d7b902010-10-29 09:26:59 +00004189 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004190 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004191}
4192
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004193/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004194bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4195 StringRef IDVal = DirectiveID.getIdentifier();
4196 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004197 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004198 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004199 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004200 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004201 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004202 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004203 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004204 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004205 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004206 return true;
4207}
4208
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004209/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004210/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004211bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004212 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4213 for (;;) {
4214 const MCExpr *Value;
4215 if (getParser().ParseExpression(Value))
4216 return true;
4217
Chris Lattnerc35681b2010-01-19 19:46:13 +00004218 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004219
4220 if (getLexer().is(AsmToken::EndOfStatement))
4221 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004222
Kevin Enderbyccab3172009-09-15 00:27:25 +00004223 // FIXME: Improve diagnostic.
4224 if (getLexer().isNot(AsmToken::Comma))
4225 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004226 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004227 }
4228 }
4229
Sean Callanana83fd7d2010-01-19 20:27:46 +00004230 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004231 return false;
4232}
4233
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004234/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004235/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004236bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004237 if (getLexer().isNot(AsmToken::EndOfStatement))
4238 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004239 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004240
4241 // TODO: set thumb mode
4242 // TODO: tell the MC streamer the mode
4243 // getParser().getStreamer().Emit???();
4244 return false;
4245}
4246
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004247/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004248/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004249bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004250 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4251 bool isMachO = MAI.hasSubsectionsViaSymbols();
4252 StringRef Name;
4253
4254 // Darwin asm has function name after .thumb_func direction
4255 // ELF doesn't
4256 if (isMachO) {
4257 const AsmToken &Tok = Parser.getTok();
4258 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4259 return Error(L, "unexpected token in .thumb_func directive");
4260 Name = Tok.getString();
4261 Parser.Lex(); // Consume the identifier token.
4262 }
4263
Kevin Enderby146dcf22009-10-15 20:48:48 +00004264 if (getLexer().isNot(AsmToken::EndOfStatement))
4265 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004266 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004267
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004268 // FIXME: assuming function name will be the line following .thumb_func
4269 if (!isMachO) {
4270 Name = Parser.getTok().getString();
4271 }
4272
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004273 // Mark symbol as a thumb symbol.
4274 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4275 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004276 return false;
4277}
4278
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004279/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004280/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004281bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004282 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004283 if (Tok.isNot(AsmToken::Identifier))
4284 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004285 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004286 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004287 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004288 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004289 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004290 else
4291 return Error(L, "unrecognized syntax mode in .syntax directive");
4292
4293 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004294 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004295 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004296
4297 // TODO tell the MC streamer the mode
4298 // getParser().getStreamer().Emit???();
4299 return false;
4300}
4301
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004302/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00004303/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004304bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004305 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004306 if (Tok.isNot(AsmToken::Integer))
4307 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00004308 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00004309 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004310 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004311 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004312 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004313 else
4314 return Error(L, "invalid operand to .code directive");
4315
4316 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004317 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004318 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004319
Evan Cheng284b4672011-07-08 22:36:29 +00004320 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004321 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004322 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004323 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00004324 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004325 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004326 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004327 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00004328 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00004329
Kevin Enderby146dcf22009-10-15 20:48:48 +00004330 return false;
4331}
4332
Sean Callanan643a5572010-04-07 20:29:34 +00004333extern "C" void LLVMInitializeARMAsmLexer();
4334
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004335/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00004336extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00004337 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4338 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00004339 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004340}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004341
Chris Lattner3e4582a2010-09-06 19:11:01 +00004342#define GET_REGISTER_MATCHER
4343#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004344#include "ARMGenAsmMatcher.inc"