blob: 355bb98e8bc487c06d67644c922ebac8377d0884 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-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 Grosbacha1109882011-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 Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-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 Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-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 Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-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 Grosbachc27d4f92011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000161 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000162
163 // Asm Match Converter Methods
Jim Grosbacha77295d2011-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 Grosbacheeec0252011-09-08 00:39:19 +0000168 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000170 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000172 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000174 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000176 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000180 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-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 Grosbach2fd2b872011-08-10 20:29:19 +0000190 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000192 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000194 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000196 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000198
199 bool validateInstruction(MCInst &Inst,
200 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000201 void processInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000203 bool shouldOmitCCOutOperand(StringRef Mnemonic,
204 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000205
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000206public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000207 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000208 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000209 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresV6,
211 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000212 };
213
Evan Chengffc0e732011-07-09 05:47:46 +0000214 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000215 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000216 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000217
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000219 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000220
221 // Not in an ITBlock to start with.
222 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000223 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000224
Jim Grosbach1355cf12011-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 Grosbach189610f2011-07-26 18:25:39 +0000228 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000229 bool ParseDirective(AsmToken DirectiveID);
230
Jim Grosbach47a0d522011-08-16 20:45:50 +0000231 unsigned checkTargetMatchPredicate(MCInst &Inst);
232
Jim Grosbach1355cf12011-07-26 17:10:22 +0000233 bool MatchAndEmitInstruction(SMLoc IDLoc,
234 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
235 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000236};
Jim Grosbach16c74252010-10-29 14:46:02 +0000237} // end anonymous namespace
238
Chris Lattner3a697562010-10-28 17:20:03 +0000239namespace {
240
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000241/// ARMOperand - Instances of this class represent a parsed ARM machine
242/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000243class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000244 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000245 CondCode,
Jim Grosbachd67641b2010-12-06 18:21:12 +0000246 CCOut,
Jim Grosbach89df9962011-08-26 21:43:41 +0000247 ITCondMask,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000248 CoprocNum,
249 CoprocReg,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000250 Immediate,
Jim Grosbach9d390362011-10-03 23:38:36 +0000251 FPImmediate,
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000252 MemBarrierOpt,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000253 Memory,
Jim Grosbach7ce05792011-08-03 23:50:40 +0000254 PostIndexRegister,
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000255 MSRMask,
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000256 ProcIFlags,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000257 Register,
Bill Wendling8d5acb72010-11-06 19:56:04 +0000258 RegisterList,
Bill Wendling0f630752010-11-17 04:32:08 +0000259 DPRRegisterList,
260 SPRRegisterList,
Jim Grosbache8606dc2011-07-13 17:50:29 +0000261 ShiftedRegister,
Owen Anderson92a20222011-07-21 18:54:16 +0000262 ShiftedImmediate,
Jim Grosbach580f4a92011-07-25 22:20:28 +0000263 ShifterImmediate,
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000264 RotateImmediate,
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000265 BitfieldDescriptor,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000266 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000267 } Kind;
268
Sean Callanan76264762010-04-02 22:27:05 +0000269 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000270 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000271
272 union {
273 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000274 ARMCC::CondCodes Val;
275 } CC;
276
277 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000278 unsigned Val;
279 } Cop;
280
281 struct {
Jim Grosbach89df9962011-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 Lopesa2b6e412011-02-14 13:09:44 +0000290 ARM_PROC::IFlags Val;
291 } IFlags;
292
293 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000294 unsigned Val;
295 } MMask;
296
297 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000298 const char *Data;
299 unsigned Length;
300 } Tok;
301
302 struct {
303 unsigned RegNum;
304 } Reg;
305
Bill Wendling8155e5b2010-11-06 22:19:43 +0000306 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000307 const MCExpr *Val;
308 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000309
Jim Grosbach9d390362011-10-03 23:38:36 +0000310 struct {
311 unsigned Val; // encoded 8-bit representation
312 } FPImm;
313
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000314 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000315 struct {
316 unsigned BaseRegNum;
Jim Grosbach7ce05792011-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 Grosbach0d6fac32011-08-05 22:03:36 +0000322 unsigned ShiftImm; // shift for OffsetReg.
Jim Grosbach7ce05792011-08-03 23:50:40 +0000323 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000324 } Mem;
Owen Anderson00828302011-03-18 22:50:18 +0000325
326 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000327 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000328 bool isAdd;
329 ARM_AM::ShiftOpc ShiftTy;
330 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000331 } PostIdxReg;
332
333 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000334 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000335 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000336 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000337 struct {
338 ARM_AM::ShiftOpc ShiftTy;
339 unsigned SrcReg;
340 unsigned ShiftReg;
341 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000342 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000343 struct {
344 ARM_AM::ShiftOpc ShiftTy;
345 unsigned SrcReg;
346 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000347 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000348 struct {
349 unsigned Imm;
350 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000351 struct {
352 unsigned LSB;
353 unsigned Width;
354 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000355 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000356
Bill Wendling146018f2010-11-06 21:42:12 +0000357 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
358public:
Sean Callanan76264762010-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 Dunbar8462b302010-08-11 06:36:53 +0000364 case CondCode:
365 CC = o.CC;
366 break;
Jim Grosbach89df9962011-08-26 21:43:41 +0000367 case ITCondMask:
368 ITMask = o.ITMask;
369 break;
Sean Callanan76264762010-04-02 22:27:05 +0000370 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000371 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000372 break;
Jim Grosbachd67641b2010-12-06 18:21:12 +0000373 case CCOut:
Sean Callanan76264762010-04-02 22:27:05 +0000374 case Register:
375 Reg = o.Reg;
376 break;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000377 case RegisterList:
Bill Wendling0f630752010-11-17 04:32:08 +0000378 case DPRRegisterList:
379 case SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000380 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000381 break;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000382 case CoprocNum:
383 case CoprocReg:
384 Cop = o.Cop;
385 break;
Sean Callanan76264762010-04-02 22:27:05 +0000386 case Immediate:
387 Imm = o.Imm;
388 break;
Jim Grosbach9d390362011-10-03 23:38:36 +0000389 case FPImmediate:
390 FPImm = o.FPImm;
391 break;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000392 case MemBarrierOpt:
393 MBOpt = o.MBOpt;
394 break;
Sean Callanan76264762010-04-02 22:27:05 +0000395 case Memory:
396 Mem = o.Mem;
397 break;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000398 case PostIndexRegister:
399 PostIdxReg = o.PostIdxReg;
400 break;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000401 case MSRMask:
402 MMask = o.MMask;
403 break;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000404 case ProcIFlags:
405 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000406 break;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000407 case ShifterImmediate:
408 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000409 break;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000410 case ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000411 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000412 break;
Owen Anderson92a20222011-07-21 18:54:16 +0000413 case ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000414 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000415 break;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000416 case RotateImmediate:
417 RotImm = o.RotImm;
418 break;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000419 case BitfieldDescriptor:
420 Bitfield = o.Bitfield;
421 break;
Sean Callanan76264762010-04-02 22:27:05 +0000422 }
423 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000424
Sean Callanan76264762010-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 Enderbya7ba3a82009-10-06 22:26:42 +0000429
Daniel Dunbar8462b302010-08-11 06:36:53 +0000430 ARMCC::CondCodes getCondCode() const {
431 assert(Kind == CondCode && "Invalid access!");
432 return CC.Val;
433 }
434
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000435 unsigned getCoproc() const {
436 assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
437 return Cop.Val;
438 }
439
Kevin Enderbya7ba3a82009-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 Kramer6aa49432010-12-07 15:50:35 +0000446 assert((Kind == Register || Kind == CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000447 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000448 }
449
Bill Wendling5fa22a12010-11-09 23:28:44 +0000450 const SmallVectorImpl<unsigned> &getRegList() const {
Bill Wendling0f630752010-11-17 04:32:08 +0000451 assert((Kind == RegisterList || Kind == DPRRegisterList ||
452 Kind == SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000453 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000454 }
455
Kevin Enderbycfe07242009-10-13 22:19:02 +0000456 const MCExpr *getImm() const {
457 assert(Kind == Immediate && "Invalid access!");
458 return Imm.Val;
459 }
460
Jim Grosbach9d390362011-10-03 23:38:36 +0000461 unsigned getFPImm() const {
462 assert(Kind == FPImmediate && "Invalid access!");
463 return FPImm.Val;
464 }
465
Bruno Cardoso Lopes706d9462011-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 Lopesa2b6e412011-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 Lopes584bf7b2011-02-18 19:45:59 +0000476 unsigned getMSRMask() const {
477 assert(Kind == MSRMask && "Invalid access!");
478 return MMask.Val;
479 }
480
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000481 bool isCoprocNum() const { return Kind == CoprocNum; }
482 bool isCoprocReg() const { return Kind == CoprocReg; }
Daniel Dunbar8462b302010-08-11 06:36:53 +0000483 bool isCondCode() const { return Kind == CondCode; }
Jim Grosbachd67641b2010-12-06 18:21:12 +0000484 bool isCCOut() const { return Kind == CCOut; }
Jim Grosbach89df9962011-08-26 21:43:41 +0000485 bool isITMask() const { return Kind == ITCondMask; }
486 bool isITCondCode() const { return Kind == CondCode; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000487 bool isImm() const { return Kind == Immediate; }
Jim Grosbach9d390362011-10-03 23:38:36 +0000488 bool isFPImm() const { return Kind == FPImmediate; }
Jim Grosbacha77295d2011-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 Grosbach72f39f82011-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 Grosbach6b8f1e32011-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 Grosbach83ab0702011-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 Grosbach7c6e42e2011-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 Grosbachf4943352011-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 Grosbach4a5ffb32011-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 Grosbachfff76ee2011-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 Grosbachffa32252011-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 Grosbached838482011-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 Grosbach70939ee2011-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 Grosbachf6c05252011-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 Grosbach6bc1dbc2011-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 Grosbach6b8f1e32011-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 Grosbachc27d4f92011-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 Wendlingb32e7842010-11-08 00:32:40 +0000635 bool isReg() const { return Kind == Register; }
Bill Wendling8d5acb72010-11-06 19:56:04 +0000636 bool isRegList() const { return Kind == RegisterList; }
Bill Wendling0f630752010-11-17 04:32:08 +0000637 bool isDPRRegList() const { return Kind == DPRRegisterList; }
638 bool isSPRRegList() const { return Kind == SPRRegisterList; }
Chris Lattner14b93852010-10-29 00:27:31 +0000639 bool isToken() const { return Kind == Token; }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000640 bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
Chris Lattner14b93852010-10-29 00:27:31 +0000641 bool isMemory() const { return Kind == Memory; }
Jim Grosbach580f4a92011-07-25 22:20:28 +0000642 bool isShifterImm() const { return Kind == ShifterImmediate; }
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000643 bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
644 bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000645 bool isRotImm() const { return Kind == RotateImmediate; }
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000646 bool isBitfield() const { return Kind == BitfieldDescriptor; }
Jim Grosbachf4fa3d62011-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 Grosbach7ce05792011-08-03 23:50:40 +0000651 bool isMemNoOffset() const {
652 if (Kind != Memory)
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000653 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000654 // No offset of any kind.
655 return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0;
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000656 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000657 bool isAddrMode2() const {
658 if (Kind != Memory)
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000659 return false;
Jim Grosbach7ce05792011-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 Lopesac79e4c2011-04-04 17:18:19 +0000666 }
Jim Grosbach039c2e12011-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 Grosbach2fd2b872011-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 Grosbach251bf252011-08-10 21:56:18 +0000697 // Special case, #-0 is INT32_MIN.
698 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000699 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000700 bool isAddrMode5() const {
701 if (Kind != Memory)
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000702 return false;
Jim Grosbach7ce05792011-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 Anderson0da10cf2011-08-29 19:36:44 +0000708 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
709 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000710 }
Jim Grosbach7f739be2011-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 Grosbach7ce05792011-08-03 23:50:40 +0000723 bool isMemRegOffset() const {
724 if (Kind != Memory || !Mem.OffsetRegNum)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000725 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000726 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000727 }
Jim Grosbachab899c12011-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 Grosbach7ce05792011-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 Wendlingef4a68b2010-11-30 07:44:32 +0000743 return false;
Jim Grosbach60f91a32011-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 Grosbachecd85892011-08-19 18:13:48 +0000754 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
755 }
Jim Grosbach38466302011-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 Grosbach48ff5ff2011-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 Grosbachecd85892011-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 Wendlingef4a68b2010-11-30 07:44:32 +0000781 }
Jim Grosbacha77295d2011-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 Grosbachb6aed502011-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 Grosbach7ce05792011-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 Anderson4d2a0012011-09-23 22:25:02 +0000804 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000805 }
Jim Grosbachf0eee6e2011-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 Grosbacha8307dd2011-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 Grosbach7ce05792011-08-03 23:50:40 +0000836 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-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 Grosbach7ce05792011-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 Anderson0da10cf2011-08-29 19:36:44 +0000848 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-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 Anderson63553c72011-08-29 17:17:09 +0000856 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000857 }
858
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000859 bool isMSRMask() const { return Kind == MSRMask; }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000860 bool isProcIFlags() const { return Kind == ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000861
862 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-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 Dunbar3483aca2010-08-11 05:24:50 +0000867 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
868 else
869 Inst.addOperand(MCOperand::CreateExpr(Expr));
870 }
871
Daniel Dunbar8462b302010-08-11 06:36:53 +0000872 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000873 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000874 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000875 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
876 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000877 }
878
Bruno Cardoso Lopesfafde7f2011-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 Grosbach89df9962011-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 Lopesfafde7f2011-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 Grosbachd67641b2010-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 Enderbya7ba3a82009-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 Grosbachaf6981f2011-07-25 20:49:51 +0000909 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000910 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-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 Grosbache8606dc2011-07-13 17:50:29 +0000914 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000915 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000916 }
917
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000918 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000919 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000920 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
921 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000922 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000923 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000924 }
925
Jim Grosbach580f4a92011-07-25 22:20:28 +0000926 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000928 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
929 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +0000930 }
931
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000932 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +0000933 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +0000934 const SmallVectorImpl<unsigned> &RegList = getRegList();
935 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +0000936 I = RegList.begin(), E = RegList.end(); I != E; ++I)
937 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000938 }
939
Bill Wendling0f630752010-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 Grosbach7e1547e2011-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 Grosbach293a2ee2011-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 Dunbar3483aca2010-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 Grosbach16c74252010-10-29 14:46:02 +0000969
Jim Grosbach9d390362011-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 Grosbacha77295d2011-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 Grosbach72f39f82011-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 Grosbach6b8f1e32011-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 Grosbach83ab0702011-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 Grosbach7c6e42e2011-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 Grosbachf4943352011-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 Grosbach4a5ffb32011-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 Grosbachfff76ee2011-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 Grosbachffa32252011-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 Grosbached838482011-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 Grosbach70939ee2011-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 Grosbachf6c05252011-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 Grosbach6bc1dbc2011-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 Grosbach6b8f1e32011-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 Grosbachc27d4f92011-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 Lopes706d9462011-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 Grosbach7ce05792011-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 Lopes505f3cd2011-03-24 21:04:58 +00001096 }
1097
Jim Grosbach7ce05792011-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 Grosbachdd32ba32011-08-11 22:05:09 +00001111 Mem.ShiftImm, Mem.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001112 }
Jim Grosbach7ce05792011-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 Lopesae085542011-03-31 23:26:08 +00001116 }
1117
Jim Grosbach039c2e12011-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 Grosbach2fd2b872011-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 Grosbach251bf252011-08-10 21:56:18 +00001158 return;
Jim Grosbach2fd2b872011-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 Grosbach251bf252011-08-10 21:56:18 +00001168 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001169 Inst.addOperand(MCOperand::CreateReg(0));
1170 Inst.addOperand(MCOperand::CreateImm(Val));
1171 }
1172
Jim Grosbach7ce05792011-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 Lopesac79e4c2011-04-04 17:18:19 +00001184 }
1185
Jim Grosbacha77295d2011-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 Grosbachb6aed502011-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 Grosbach7ce05792011-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 Lattner14b93852010-10-29 00:27:31 +00001206 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001207
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001208 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1209 addMemImm8OffsetOperands(Inst, N);
1210 }
1211
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001212 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001213 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-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 Grosbach7ce05792011-08-03 23:50:40 +00001231 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-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 Grosbach7ce05792011-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 Wendlingf4caf692010-12-14 03:36:38 +00001244 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001245
Jim Grosbach7f739be2011-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 Grosbach7ce05792011-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 Grosbach0d6fac32011-08-05 22:03:36 +00001261 Mem.ShiftImm, Mem.ShiftType);
Jim Grosbach7ce05792011-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 Grosbachab899c12011-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 Grosbach7ce05792011-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 Grosbach60f91a32011-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 Grosbach38466302011-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 Grosbach48ff5ff2011-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 Grosbachecd85892011-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 Grosbach7ce05792011-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 Anderson63553c72011-08-29 17:17:09 +00001314 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-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 Grosbachf4fa3d62011-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 Wendlingef4a68b2010-11-30 07:44:32 +00001334 }
1335
Bruno Cardoso Lopes584bf7b2011-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 Lopesa2b6e412011-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 Grosbachb7f689b2011-07-13 15:34:57 +00001346 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001347
Jim Grosbach89df9962011-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 Lattner3a697562010-10-28 17:20:03 +00001356 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
1357 ARMOperand *Op = new ARMOperand(CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001358 Op->CC.Val = CC;
1359 Op->StartLoc = S;
1360 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001361 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001362 }
1363
Bruno Cardoso Lopesfafde7f2011-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 Grosbachd67641b2010-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 Lattner3a697562010-10-28 17:20:03 +00001388 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
1389 ARMOperand *Op = new ARMOperand(Token);
Sean Callanan76264762010-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 Lattner3a697562010-10-28 17:20:03 +00001394 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001395 }
1396
Bill Wendling50d0f582010-11-18 23:43:05 +00001397 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Chris Lattner3a697562010-10-28 17:20:03 +00001398 ARMOperand *Op = new ARMOperand(Register);
Sean Callanan76264762010-04-02 22:27:05 +00001399 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001400 Op->StartLoc = S;
1401 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001402 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001403 }
1404
Jim Grosbache8606dc2011-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 Grosbachaf6981f2011-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 Grosbache8606dc2011-07-13 17:50:29 +00001415 Op->StartLoc = S;
1416 Op->EndLoc = E;
1417 return Op;
1418 }
1419
Owen Anderson92a20222011-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 Grosbachaf6981f2011-07-25 20:49:51 +00001425 Op->RegShiftedImm.ShiftTy = ShTy;
1426 Op->RegShiftedImm.SrcReg = SrcReg;
1427 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001428 Op->StartLoc = S;
1429 Op->EndLoc = E;
1430 return Op;
1431 }
1432
Jim Grosbach580f4a92011-07-25 22:20:28 +00001433 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001434 SMLoc S, SMLoc E) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00001435 ARMOperand *Op = new ARMOperand(ShifterImmediate);
1436 Op->ShifterImm.isASR = isASR;
1437 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001438 Op->StartLoc = S;
1439 Op->EndLoc = E;
1440 return Op;
1441 }
1442
Jim Grosbach7e1547e2011-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 Grosbach293a2ee2011-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 Wendling7729e062010-11-09 22:44:22 +00001461 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001462 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001463 SMLoc StartLoc, SMLoc EndLoc) {
Bill Wendling0f630752010-11-17 04:32:08 +00001464 KindTy Kind = RegisterList;
1465
Jim Grosbachd300b942011-09-13 22:56:44 +00001466 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Bill Wendling0f630752010-11-17 04:32:08 +00001467 Kind = DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001468 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001469 contains(Regs.front().first))
Bill Wendling0f630752010-11-17 04:32:08 +00001470 Kind = SPRRegisterList;
1471
1472 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001473 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001474 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001475 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001476 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001477 Op->StartLoc = StartLoc;
1478 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001479 return Op;
1480 }
1481
Chris Lattner3a697562010-10-28 17:20:03 +00001482 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
1483 ARMOperand *Op = new ARMOperand(Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001484 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001485 Op->StartLoc = S;
1486 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001487 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001488 }
1489
Jim Grosbach9d390362011-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 Grosbach7ce05792011-08-03 23:50:40 +00001498 static ARMOperand *CreateMem(unsigned BaseRegNum,
1499 const MCConstantExpr *OffsetImm,
1500 unsigned OffsetRegNum,
1501 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001502 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001504 SMLoc S, SMLoc E) {
1505 ARMOperand *Op = new ARMOperand(Memory);
Sean Callanan76264762010-04-02 22:27:05 +00001506 Op->Mem.BaseRegNum = BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001507 Op->Mem.OffsetImm = OffsetImm;
1508 Op->Mem.OffsetRegNum = OffsetRegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001509 Op->Mem.ShiftType = ShiftType;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001510 Op->Mem.ShiftImm = ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001511 Op->Mem.isNegative = isNegative;
1512 Op->StartLoc = S;
1513 Op->EndLoc = E;
1514 return Op;
1515 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001516
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001517 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1518 ARM_AM::ShiftOpc ShiftTy,
1519 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001520 SMLoc S, SMLoc E) {
1521 ARMOperand *Op = new ARMOperand(PostIndexRegister);
1522 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001523 Op->PostIdxReg.isAdd = isAdd;
1524 Op->PostIdxReg.ShiftTy = ShiftTy;
1525 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001526 Op->StartLoc = S;
1527 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001528 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001529 }
Bruno Cardoso Lopes706d9462011-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 Lopesa2b6e412011-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 Lopes584bf7b2011-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 Enderbya7ba3a82009-10-06 22:26:42 +00001554};
1555
1556} // end anonymous namespace.
1557
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001558void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001559 switch (Kind) {
Jim Grosbach9d390362011-10-03 23:38:36 +00001560 case FPImmediate:
1561 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1562 << ") >";
1563 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001564 case CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001565 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001566 break;
Jim Grosbachd67641b2010-12-06 18:21:12 +00001567 case CCOut:
1568 OS << "<ccout " << getReg() << ">";
1569 break;
Jim Grosbach89df9962011-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 Lopesfafde7f2011-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 Lopes584bf7b2011-02-18 19:45:59 +00001584 case MSRMask:
1585 OS << "<mask: " << getMSRMask() << ">";
1586 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001587 case Immediate:
1588 getImm()->print(OS);
1589 break;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001590 case MemBarrierOpt:
1591 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1592 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001593 case Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001594 OS << "<memory "
Jim Grosbach7ce05792011-08-03 23:50:40 +00001595 << " base:" << Mem.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001596 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001597 break;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001598 case PostIndexRegister:
Jim Grosbachf4fa3d62011-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 Grosbach7ce05792011-08-03 23:50:40 +00001605 break;
Bruno Cardoso Lopesa2b6e412011-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 Dunbarfa315de2010-08-11 06:37:12 +00001615 case Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001616 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001617 break;
Jim Grosbach580f4a92011-07-25 22:20:28 +00001618 case ShifterImmediate:
1619 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1620 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001621 break;
1622 case ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001623 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-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 Grosbache8606dc2011-07-13 17:50:29 +00001628 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001629 break;
Owen Anderson92a20222011-07-21 18:54:16 +00001630 case ShiftedImmediate:
1631 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001632 << RegShiftedImm.SrcReg
1633 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1634 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001635 << ">";
1636 break;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001637 case RotateImmediate:
1638 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1639 break;
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001640 case BitfieldDescriptor:
1641 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1642 << ", width: " << Bitfield.Width << ">";
1643 break;
Bill Wendling0f630752010-11-17 04:32:08 +00001644 case RegisterList:
1645 case DPRRegisterList:
1646 case SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001647 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001648
Bill Wendling5fa22a12010-11-09 23:28:44 +00001649 const SmallVectorImpl<unsigned> &RegList = getRegList();
1650 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001651 I = RegList.begin(), E = RegList.end(); I != E; ) {
1652 OS << *I;
1653 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001654 }
1655
1656 OS << ">";
1657 break;
1658 }
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001659 case Token:
1660 OS << "'" << getToken() << "'";
1661 break;
1662 }
1663}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001664
1665/// @name Auto-generated Match Functions
1666/// {
1667
1668static unsigned MatchRegisterName(StringRef Name);
1669
1670/// }
1671
Bob Wilson69df7232011-02-03 21:46:10 +00001672bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1673 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001674 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001675
1676 return (RegNo == (unsigned)-1);
1677}
1678
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001679/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-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 Grosbach1355cf12011-07-26 17:10:22 +00001683int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001684 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001685 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001686
Chris Lattnere5658fa2010-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 Anderson0c9f2502011-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 Wilson69df7232011-02-03 21:46:10 +00001701
Chris Lattnere5658fa2010-10-30 04:09:10 +00001702 Parser.Lex(); // Eat identifier token.
1703 return RegNum;
1704}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001705
Jim Grosbach19906722011-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 Grosbach0d87ec22011-07-26 20:41:24 +00001711int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-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 Grosbach19906722011-07-13 18:49:30 +00001728 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001729
Jim Grosbache8606dc2011-07-13 17:50:29 +00001730 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001731
Jim Grosbache8606dc2011-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 Kramereac07962011-07-14 18:41:22 +00001735 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-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 Grosbach19906722011-07-13 18:49:30 +00001752 if (getParser().ParseExpression(ShiftExpr)) {
1753 Error(ImmLoc, "invalid immediate shift value");
1754 return -1;
1755 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001756 // The expression must be evaluatable as an immediate.
1757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001758 if (!CE) {
1759 Error(ImmLoc, "invalid immediate shift value");
1760 return -1;
1761 }
Jim Grosbache8606dc2011-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 Grosbach19906722011-07-13 18:49:30 +00001769 Error(ImmLoc, "immediate shift value out of range");
1770 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001771 }
1772 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001773 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001774 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-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 Grosbache8606dc2011-07-13 17:50:29 +00001781 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001782 return -1;
1783 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001784 }
1785
Owen Anderson92a20222011-07-21 18:54:16 +00001786 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1787 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001788 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001789 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001790 else
1791 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1792 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001793
Jim Grosbach19906722011-07-13 18:49:30 +00001794 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001795}
1796
1797
Bill Wendling50d0f582010-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 Lattner3a697562010-10-28 17:20:03 +00001801///
Kevin Enderby9c41fa82009-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 Wendling50d0f582010-11-18 23:43:05 +00001804bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001805tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001806 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001807 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001808 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001809 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001810
Bill Wendling50d0f582010-11-18 23:43:05 +00001811 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001812
Chris Lattnere5658fa2010-10-30 04:09:10 +00001813 const AsmToken &ExclaimTok = Parser.getTok();
1814 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001815 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1816 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001817 Parser.Lex(); // Eat exclaim token
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00001818 }
1819
Bill Wendling50d0f582010-11-18 23:43:05 +00001820 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001821}
1822
Bruno Cardoso Lopesfafde7f2011-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 Andersone4e5e2a2011-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 Lopesfafde7f2011-02-07 21:41:25 +00001832 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-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 Lopesfafde7f2011-02-07 21:41:25 +00001849 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-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 Andersone4e5e2a2011-01-13 21:46:02 +00001863 return -1;
1864}
1865
Jim Grosbach89df9962011-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 Grosbach43904292011-07-25 20:14:50 +00001901/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-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 Grosbachf922c472011-02-12 01:34:40 +00001904ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00001905parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-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 Lopesfafde7f2011-02-07 21:41:25 +00001910 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001911 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00001912 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001913
1914 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001915 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00001916 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001917}
1918
Jim Grosbach43904292011-07-25 20:14:50 +00001919/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-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 Grosbachf922c472011-02-12 01:34:40 +00001922ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00001923parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-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 Grosbachf922c472011-02-12 01:34:40 +00001930 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001931
1932 Parser.Lex(); // Eat identifier token.
1933 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00001934 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001935}
1936
Jim Grosbachd0588e22011-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 Wendling50d0f582010-11-18 23:43:05 +00001960bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001961parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00001962 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00001963 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00001964 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00001965 Parser.Lex(); // Eat '{' token.
1966 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00001967
Jim Grosbachd0588e22011-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 Grosbachd7a2b3b2011-09-13 20:35:57 +00001986 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00001987 // Store the first register.
1988 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00001989
Jim Grosbachd0588e22011-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 Enderbyd7894f12009-10-09 21:12:28 +00002011
Jim Grosbachd0588e22011-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 Grosbach2d539692011-09-12 23:36:42 +00002024 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-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 Wendlinge7176102010-11-06 22:36:58 +00002038 }
2039
Jim Grosbachd0588e22011-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 Wendling50d0f582010-11-18 23:43:05 +00002045 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2046 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002047}
2048
Jim Grosbach43904292011-07-25 20:14:50 +00002049/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002050ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002051parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-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 Grosbach032434d2011-07-13 23:40:38 +00002060 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002061 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002062 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002063 .Case("ishst", ARM_MB::ISHST)
2064 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002065 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002066 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002067 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-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 Grosbachf922c472011-02-12 01:34:40 +00002073 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002074
2075 Parser.Lex(); // Eat identifier token.
2076 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002077 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002078}
2079
Jim Grosbach43904292011-07-25 20:14:50 +00002080/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002081ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002082parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-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
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002088 // An iflags string of "none" is interpreted to mean that none of the AIF
2089 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002090 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002091 if (IFlagsStr != "none") {
2092 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2093 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2094 .Case("a", ARM_PROC::A)
2095 .Case("i", ARM_PROC::I)
2096 .Case("f", ARM_PROC::F)
2097 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002098
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002099 // If some specific iflag is already set, it means that some letter is
2100 // present more than once, this is not acceptable.
2101 if (Flag == ~0U || (IFlags & Flag))
2102 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002103
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002104 IFlags |= Flag;
2105 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002106 }
2107
2108 Parser.Lex(); // Eat identifier token.
2109 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2110 return MatchOperand_Success;
2111}
2112
Jim Grosbach43904292011-07-25 20:14:50 +00002113/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002114ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002115parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002116 SMLoc S = Parser.getTok().getLoc();
2117 const AsmToken &Tok = Parser.getTok();
2118 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2119 StringRef Mask = Tok.getString();
2120
James Molloyacad68d2011-09-28 14:21:38 +00002121 if (isMClass()) {
2122 // See ARMv6-M 10.1.1
2123 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2124 .Case("apsr", 0)
2125 .Case("iapsr", 1)
2126 .Case("eapsr", 2)
2127 .Case("xpsr", 3)
2128 .Case("ipsr", 5)
2129 .Case("epsr", 6)
2130 .Case("iepsr", 7)
2131 .Case("msp", 8)
2132 .Case("psp", 9)
2133 .Case("primask", 16)
2134 .Case("basepri", 17)
2135 .Case("basepri_max", 18)
2136 .Case("faultmask", 19)
2137 .Case("control", 20)
2138 .Default(~0U);
2139
2140 if (FlagsVal == ~0U)
2141 return MatchOperand_NoMatch;
2142
2143 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2144 // basepri, basepri_max and faultmask only valid for V7m.
2145 return MatchOperand_NoMatch;
2146
2147 Parser.Lex(); // Eat identifier token.
2148 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2149 return MatchOperand_Success;
2150 }
2151
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002152 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2153 size_t Start = 0, Next = Mask.find('_');
2154 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002155 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002156 if (Next != StringRef::npos)
2157 Flags = Mask.slice(Next+1, Mask.size());
2158
2159 // FlagsVal contains the complete mask:
2160 // 3-0: Mask
2161 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2162 unsigned FlagsVal = 0;
2163
2164 if (SpecReg == "apsr") {
2165 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002166 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002167 .Case("g", 0x4) // same as CPSR_s
2168 .Case("nzcvqg", 0xc) // same as CPSR_fs
2169 .Default(~0U);
2170
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002171 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002172 if (!Flags.empty())
2173 return MatchOperand_NoMatch;
2174 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002175 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002176 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002177 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002178 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2179 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002180 for (int i = 0, e = Flags.size(); i != e; ++i) {
2181 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2182 .Case("c", 1)
2183 .Case("x", 2)
2184 .Case("s", 4)
2185 .Case("f", 8)
2186 .Default(~0U);
2187
2188 // If some specific flag is already set, it means that some letter is
2189 // present more than once, this is not acceptable.
2190 if (FlagsVal == ~0U || (FlagsVal & Flag))
2191 return MatchOperand_NoMatch;
2192 FlagsVal |= Flag;
2193 }
2194 } else // No match for special register.
2195 return MatchOperand_NoMatch;
2196
2197 // Special register without flags are equivalent to "fc" flags.
2198 if (!FlagsVal)
2199 FlagsVal = 0x9;
2200
2201 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2202 if (SpecReg == "spsr")
2203 FlagsVal |= 16;
2204
2205 Parser.Lex(); // Eat identifier token.
2206 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2207 return MatchOperand_Success;
2208}
2209
Jim Grosbachf6c05252011-07-21 17:23:04 +00002210ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2211parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2212 int Low, int High) {
2213 const AsmToken &Tok = Parser.getTok();
2214 if (Tok.isNot(AsmToken::Identifier)) {
2215 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2216 return MatchOperand_ParseFail;
2217 }
2218 StringRef ShiftName = Tok.getString();
2219 std::string LowerOp = LowercaseString(Op);
2220 std::string UpperOp = UppercaseString(Op);
2221 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2222 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2223 return MatchOperand_ParseFail;
2224 }
2225 Parser.Lex(); // Eat shift type token.
2226
2227 // There must be a '#' and a shift amount.
2228 if (Parser.getTok().isNot(AsmToken::Hash)) {
2229 Error(Parser.getTok().getLoc(), "'#' expected");
2230 return MatchOperand_ParseFail;
2231 }
2232 Parser.Lex(); // Eat hash token.
2233
2234 const MCExpr *ShiftAmount;
2235 SMLoc Loc = Parser.getTok().getLoc();
2236 if (getParser().ParseExpression(ShiftAmount)) {
2237 Error(Loc, "illegal expression");
2238 return MatchOperand_ParseFail;
2239 }
2240 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2241 if (!CE) {
2242 Error(Loc, "constant expression expected");
2243 return MatchOperand_ParseFail;
2244 }
2245 int Val = CE->getValue();
2246 if (Val < Low || Val > High) {
2247 Error(Loc, "immediate value out of range");
2248 return MatchOperand_ParseFail;
2249 }
2250
2251 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2252
2253 return MatchOperand_Success;
2254}
2255
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002256ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2257parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2258 const AsmToken &Tok = Parser.getTok();
2259 SMLoc S = Tok.getLoc();
2260 if (Tok.isNot(AsmToken::Identifier)) {
2261 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2262 return MatchOperand_ParseFail;
2263 }
2264 int Val = StringSwitch<int>(Tok.getString())
2265 .Case("be", 1)
2266 .Case("le", 0)
2267 .Default(-1);
2268 Parser.Lex(); // Eat the token.
2269
2270 if (Val == -1) {
2271 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2272 return MatchOperand_ParseFail;
2273 }
2274 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2275 getContext()),
2276 S, Parser.getTok().getLoc()));
2277 return MatchOperand_Success;
2278}
2279
Jim Grosbach580f4a92011-07-25 22:20:28 +00002280/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2281/// instructions. Legal values are:
2282/// lsl #n 'n' in [0,31]
2283/// asr #n 'n' in [1,32]
2284/// n == 32 encoded as n == 0.
2285ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2286parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2287 const AsmToken &Tok = Parser.getTok();
2288 SMLoc S = Tok.getLoc();
2289 if (Tok.isNot(AsmToken::Identifier)) {
2290 Error(S, "shift operator 'asr' or 'lsl' expected");
2291 return MatchOperand_ParseFail;
2292 }
2293 StringRef ShiftName = Tok.getString();
2294 bool isASR;
2295 if (ShiftName == "lsl" || ShiftName == "LSL")
2296 isASR = false;
2297 else if (ShiftName == "asr" || ShiftName == "ASR")
2298 isASR = true;
2299 else {
2300 Error(S, "shift operator 'asr' or 'lsl' expected");
2301 return MatchOperand_ParseFail;
2302 }
2303 Parser.Lex(); // Eat the operator.
2304
2305 // A '#' and a shift amount.
2306 if (Parser.getTok().isNot(AsmToken::Hash)) {
2307 Error(Parser.getTok().getLoc(), "'#' expected");
2308 return MatchOperand_ParseFail;
2309 }
2310 Parser.Lex(); // Eat hash token.
2311
2312 const MCExpr *ShiftAmount;
2313 SMLoc E = Parser.getTok().getLoc();
2314 if (getParser().ParseExpression(ShiftAmount)) {
2315 Error(E, "malformed shift expression");
2316 return MatchOperand_ParseFail;
2317 }
2318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2319 if (!CE) {
2320 Error(E, "shift amount must be an immediate");
2321 return MatchOperand_ParseFail;
2322 }
2323
2324 int64_t Val = CE->getValue();
2325 if (isASR) {
2326 // Shift amount must be in [1,32]
2327 if (Val < 1 || Val > 32) {
2328 Error(E, "'asr' shift amount must be in range [1,32]");
2329 return MatchOperand_ParseFail;
2330 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002331 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2332 if (isThumb() && Val == 32) {
2333 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2334 return MatchOperand_ParseFail;
2335 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002336 if (Val == 32) Val = 0;
2337 } else {
2338 // Shift amount must be in [1,32]
2339 if (Val < 0 || Val > 31) {
2340 Error(E, "'lsr' shift amount must be in range [0,31]");
2341 return MatchOperand_ParseFail;
2342 }
2343 }
2344
2345 E = Parser.getTok().getLoc();
2346 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2347
2348 return MatchOperand_Success;
2349}
2350
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002351/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2352/// of instructions. Legal values are:
2353/// ror #n 'n' in {0, 8, 16, 24}
2354ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2355parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2356 const AsmToken &Tok = Parser.getTok();
2357 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002358 if (Tok.isNot(AsmToken::Identifier))
2359 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002360 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002361 if (ShiftName != "ror" && ShiftName != "ROR")
2362 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002363 Parser.Lex(); // Eat the operator.
2364
2365 // A '#' and a rotate amount.
2366 if (Parser.getTok().isNot(AsmToken::Hash)) {
2367 Error(Parser.getTok().getLoc(), "'#' expected");
2368 return MatchOperand_ParseFail;
2369 }
2370 Parser.Lex(); // Eat hash token.
2371
2372 const MCExpr *ShiftAmount;
2373 SMLoc E = Parser.getTok().getLoc();
2374 if (getParser().ParseExpression(ShiftAmount)) {
2375 Error(E, "malformed rotate expression");
2376 return MatchOperand_ParseFail;
2377 }
2378 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2379 if (!CE) {
2380 Error(E, "rotate amount must be an immediate");
2381 return MatchOperand_ParseFail;
2382 }
2383
2384 int64_t Val = CE->getValue();
2385 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2386 // normally, zero is represented in asm by omitting the rotate operand
2387 // entirely.
2388 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2389 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2390 return MatchOperand_ParseFail;
2391 }
2392
2393 E = Parser.getTok().getLoc();
2394 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2395
2396 return MatchOperand_Success;
2397}
2398
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002399ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2400parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2401 SMLoc S = Parser.getTok().getLoc();
2402 // The bitfield descriptor is really two operands, the LSB and the width.
2403 if (Parser.getTok().isNot(AsmToken::Hash)) {
2404 Error(Parser.getTok().getLoc(), "'#' expected");
2405 return MatchOperand_ParseFail;
2406 }
2407 Parser.Lex(); // Eat hash token.
2408
2409 const MCExpr *LSBExpr;
2410 SMLoc E = Parser.getTok().getLoc();
2411 if (getParser().ParseExpression(LSBExpr)) {
2412 Error(E, "malformed immediate expression");
2413 return MatchOperand_ParseFail;
2414 }
2415 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2416 if (!CE) {
2417 Error(E, "'lsb' operand must be an immediate");
2418 return MatchOperand_ParseFail;
2419 }
2420
2421 int64_t LSB = CE->getValue();
2422 // The LSB must be in the range [0,31]
2423 if (LSB < 0 || LSB > 31) {
2424 Error(E, "'lsb' operand must be in the range [0,31]");
2425 return MatchOperand_ParseFail;
2426 }
2427 E = Parser.getTok().getLoc();
2428
2429 // Expect another immediate operand.
2430 if (Parser.getTok().isNot(AsmToken::Comma)) {
2431 Error(Parser.getTok().getLoc(), "too few operands");
2432 return MatchOperand_ParseFail;
2433 }
2434 Parser.Lex(); // Eat hash token.
2435 if (Parser.getTok().isNot(AsmToken::Hash)) {
2436 Error(Parser.getTok().getLoc(), "'#' expected");
2437 return MatchOperand_ParseFail;
2438 }
2439 Parser.Lex(); // Eat hash token.
2440
2441 const MCExpr *WidthExpr;
2442 if (getParser().ParseExpression(WidthExpr)) {
2443 Error(E, "malformed immediate expression");
2444 return MatchOperand_ParseFail;
2445 }
2446 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2447 if (!CE) {
2448 Error(E, "'width' operand must be an immediate");
2449 return MatchOperand_ParseFail;
2450 }
2451
2452 int64_t Width = CE->getValue();
2453 // The LSB must be in the range [1,32-lsb]
2454 if (Width < 1 || Width > 32 - LSB) {
2455 Error(E, "'width' operand must be in the range [1,32-lsb]");
2456 return MatchOperand_ParseFail;
2457 }
2458 E = Parser.getTok().getLoc();
2459
2460 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2461
2462 return MatchOperand_Success;
2463}
2464
Jim Grosbach7ce05792011-08-03 23:50:40 +00002465ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2466parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2467 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002468 // postidx_reg := '+' register {, shift}
2469 // | '-' register {, shift}
2470 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002471
2472 // This method must return MatchOperand_NoMatch without consuming any tokens
2473 // in the case where there is no match, as other alternatives take other
2474 // parse methods.
2475 AsmToken Tok = Parser.getTok();
2476 SMLoc S = Tok.getLoc();
2477 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002478 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002479 int Reg = -1;
2480 if (Tok.is(AsmToken::Plus)) {
2481 Parser.Lex(); // Eat the '+' token.
2482 haveEaten = true;
2483 } else if (Tok.is(AsmToken::Minus)) {
2484 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002485 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002486 haveEaten = true;
2487 }
2488 if (Parser.getTok().is(AsmToken::Identifier))
2489 Reg = tryParseRegister();
2490 if (Reg == -1) {
2491 if (!haveEaten)
2492 return MatchOperand_NoMatch;
2493 Error(Parser.getTok().getLoc(), "register expected");
2494 return MatchOperand_ParseFail;
2495 }
2496 SMLoc E = Parser.getTok().getLoc();
2497
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002498 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2499 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002500 if (Parser.getTok().is(AsmToken::Comma)) {
2501 Parser.Lex(); // Eat the ','.
2502 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2503 return MatchOperand_ParseFail;
2504 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002505
2506 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2507 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002508
2509 return MatchOperand_Success;
2510}
2511
Jim Grosbach251bf252011-08-10 21:56:18 +00002512ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2513parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2514 // Check for a post-index addressing register operand. Specifically:
2515 // am3offset := '+' register
2516 // | '-' register
2517 // | register
2518 // | # imm
2519 // | # + imm
2520 // | # - imm
2521
2522 // This method must return MatchOperand_NoMatch without consuming any tokens
2523 // in the case where there is no match, as other alternatives take other
2524 // parse methods.
2525 AsmToken Tok = Parser.getTok();
2526 SMLoc S = Tok.getLoc();
2527
2528 // Do immediates first, as we always parse those if we have a '#'.
2529 if (Parser.getTok().is(AsmToken::Hash)) {
2530 Parser.Lex(); // Eat the '#'.
2531 // Explicitly look for a '-', as we need to encode negative zero
2532 // differently.
2533 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2534 const MCExpr *Offset;
2535 if (getParser().ParseExpression(Offset))
2536 return MatchOperand_ParseFail;
2537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2538 if (!CE) {
2539 Error(S, "constant expression expected");
2540 return MatchOperand_ParseFail;
2541 }
2542 SMLoc E = Tok.getLoc();
2543 // Negative zero is encoded as the flag value INT32_MIN.
2544 int32_t Val = CE->getValue();
2545 if (isNegative && Val == 0)
2546 Val = INT32_MIN;
2547
2548 Operands.push_back(
2549 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2550
2551 return MatchOperand_Success;
2552 }
2553
2554
2555 bool haveEaten = false;
2556 bool isAdd = true;
2557 int Reg = -1;
2558 if (Tok.is(AsmToken::Plus)) {
2559 Parser.Lex(); // Eat the '+' token.
2560 haveEaten = true;
2561 } else if (Tok.is(AsmToken::Minus)) {
2562 Parser.Lex(); // Eat the '-' token.
2563 isAdd = false;
2564 haveEaten = true;
2565 }
2566 if (Parser.getTok().is(AsmToken::Identifier))
2567 Reg = tryParseRegister();
2568 if (Reg == -1) {
2569 if (!haveEaten)
2570 return MatchOperand_NoMatch;
2571 Error(Parser.getTok().getLoc(), "register expected");
2572 return MatchOperand_ParseFail;
2573 }
2574 SMLoc E = Parser.getTok().getLoc();
2575
2576 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2577 0, S, E));
2578
2579 return MatchOperand_Success;
2580}
2581
Jim Grosbacha77295d2011-09-08 22:07:06 +00002582/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2583/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2584/// when they refer multiple MIOperands inside a single one.
2585bool ARMAsmParser::
2586cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2587 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2588 // Rt, Rt2
2589 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2590 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2591 // Create a writeback register dummy placeholder.
2592 Inst.addOperand(MCOperand::CreateReg(0));
2593 // addr
2594 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2595 // pred
2596 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2597 return true;
2598}
2599
2600/// cvtT2StrdPre - Convert parsed operands to MCInst.
2601/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2602/// when they refer multiple MIOperands inside a single one.
2603bool ARMAsmParser::
2604cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2605 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2606 // Create a writeback register dummy placeholder.
2607 Inst.addOperand(MCOperand::CreateReg(0));
2608 // Rt, Rt2
2609 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2610 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2611 // addr
2612 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2613 // pred
2614 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2615 return true;
2616}
2617
Jim Grosbacheeec0252011-09-08 00:39:19 +00002618/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2619/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2620/// when they refer multiple MIOperands inside a single one.
2621bool ARMAsmParser::
2622cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2623 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2624 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2625
2626 // Create a writeback register dummy placeholder.
2627 Inst.addOperand(MCOperand::CreateImm(0));
2628
2629 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2630 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2631 return true;
2632}
2633
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002634/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2635/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2636/// when they refer multiple MIOperands inside a single one.
2637bool ARMAsmParser::
2638cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2639 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2640 // Create a writeback register dummy placeholder.
2641 Inst.addOperand(MCOperand::CreateImm(0));
2642 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2643 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2644 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2645 return true;
2646}
2647
Jim Grosbach1355cf12011-07-26 17:10:22 +00002648/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002649/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2650/// when they refer multiple MIOperands inside a single one.
2651bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002652cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002653 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2654 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2655
2656 // Create a writeback register dummy placeholder.
2657 Inst.addOperand(MCOperand::CreateImm(0));
2658
Jim Grosbach7ce05792011-08-03 23:50:40 +00002659 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002660 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2661 return true;
2662}
2663
Owen Anderson9ab0f252011-08-26 20:43:14 +00002664/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2665/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2666/// when they refer multiple MIOperands inside a single one.
2667bool ARMAsmParser::
2668cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2669 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2670 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2671
2672 // Create a writeback register dummy placeholder.
2673 Inst.addOperand(MCOperand::CreateImm(0));
2674
2675 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2676 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2677 return true;
2678}
2679
2680
Jim Grosbach548340c2011-08-11 19:22:40 +00002681/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2682/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2683/// when they refer multiple MIOperands inside a single one.
2684bool ARMAsmParser::
2685cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2686 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2687 // Create a writeback register dummy placeholder.
2688 Inst.addOperand(MCOperand::CreateImm(0));
2689 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2690 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2691 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2692 return true;
2693}
2694
Jim Grosbach1355cf12011-07-26 17:10:22 +00002695/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002696/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2697/// when they refer multiple MIOperands inside a single one.
2698bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002699cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002700 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2701 // Create a writeback register dummy placeholder.
2702 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002703 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2704 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2705 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002706 return true;
2707}
2708
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002709/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2710/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2711/// when they refer multiple MIOperands inside a single one.
2712bool ARMAsmParser::
2713cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2714 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2715 // Create a writeback register dummy placeholder.
2716 Inst.addOperand(MCOperand::CreateImm(0));
2717 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2718 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2719 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2720 return true;
2721}
2722
Jim Grosbach7ce05792011-08-03 23:50:40 +00002723/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2724/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2725/// when they refer multiple MIOperands inside a single one.
2726bool ARMAsmParser::
2727cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2728 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2729 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002730 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002731 // Create a writeback register dummy placeholder.
2732 Inst.addOperand(MCOperand::CreateImm(0));
2733 // addr
2734 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2735 // offset
2736 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2737 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002738 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2739 return true;
2740}
2741
Jim Grosbach7ce05792011-08-03 23:50:40 +00002742/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002743/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2744/// when they refer multiple MIOperands inside a single one.
2745bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002746cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2747 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2748 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002749 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002750 // Create a writeback register dummy placeholder.
2751 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002752 // addr
2753 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2754 // offset
2755 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2756 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002757 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2758 return true;
2759}
2760
Jim Grosbach7ce05792011-08-03 23:50:40 +00002761/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002762/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2763/// when they refer multiple MIOperands inside a single one.
2764bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002765cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2766 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002767 // Create a writeback register dummy placeholder.
2768 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002769 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002770 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002771 // addr
2772 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2773 // offset
2774 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2775 // pred
2776 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2777 return true;
2778}
2779
2780/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2781/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2782/// when they refer multiple MIOperands inside a single one.
2783bool ARMAsmParser::
2784cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2785 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2786 // Create a writeback register dummy placeholder.
2787 Inst.addOperand(MCOperand::CreateImm(0));
2788 // Rt
2789 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2790 // addr
2791 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2792 // offset
2793 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2794 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002795 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2796 return true;
2797}
2798
Jim Grosbach2fd2b872011-08-10 20:29:19 +00002799/// cvtLdrdPre - Convert parsed operands to MCInst.
2800/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2801/// when they refer multiple MIOperands inside a single one.
2802bool ARMAsmParser::
2803cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2804 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2805 // Rt, Rt2
2806 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2807 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2808 // Create a writeback register dummy placeholder.
2809 Inst.addOperand(MCOperand::CreateImm(0));
2810 // addr
2811 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2812 // pred
2813 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2814 return true;
2815}
2816
Jim Grosbach14605d12011-08-11 20:28:23 +00002817/// cvtStrdPre - Convert parsed operands to MCInst.
2818/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2819/// when they refer multiple MIOperands inside a single one.
2820bool ARMAsmParser::
2821cvtStrdPre(MCInst &Inst, unsigned Opcode,
2822 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2823 // Create a writeback register dummy placeholder.
2824 Inst.addOperand(MCOperand::CreateImm(0));
2825 // Rt, Rt2
2826 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2827 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2828 // addr
2829 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2830 // pred
2831 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2832 return true;
2833}
2834
Jim Grosbach623a4542011-08-10 22:42:16 +00002835/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2836/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2837/// when they refer multiple MIOperands inside a single one.
2838bool ARMAsmParser::
2839cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2841 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2842 // Create a writeback register dummy placeholder.
2843 Inst.addOperand(MCOperand::CreateImm(0));
2844 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2845 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2846 return true;
2847}
2848
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002849/// cvtThumbMultiple- Convert parsed operands to MCInst.
2850/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2851/// when they refer multiple MIOperands inside a single one.
2852bool ARMAsmParser::
2853cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
2854 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2855 // The second source operand must be the same register as the destination
2856 // operand.
2857 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00002858 (((ARMOperand*)Operands[3])->getReg() !=
2859 ((ARMOperand*)Operands[5])->getReg()) &&
2860 (((ARMOperand*)Operands[3])->getReg() !=
2861 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002862 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00002863 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002864 return false;
2865 }
2866 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2867 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
2868 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00002869 // If we have a three-operand form, use that, else the second source operand
2870 // is just the destination operand again.
2871 if (Operands.size() == 6)
2872 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
2873 else
2874 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002875 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
2876
2877 return true;
2878}
Jim Grosbach623a4542011-08-10 22:42:16 +00002879
Bill Wendlinge7176102010-11-06 22:36:58 +00002880/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002881/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00002882bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002883parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00002884 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00002885 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002886 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00002887 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00002888 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002889
Sean Callanan18b83232010-01-19 21:44:56 +00002890 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002891 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002892 if (BaseRegNum == -1)
2893 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002894
Daniel Dunbar05710932011-01-18 05:34:17 +00002895 // The next token must either be a comma or a closing bracket.
2896 const AsmToken &Tok = Parser.getTok();
2897 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00002898 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00002899
Jim Grosbach7ce05792011-08-03 23:50:40 +00002900 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00002901 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00002902 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002903
Jim Grosbach7ce05792011-08-03 23:50:40 +00002904 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
2905 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00002906
Jim Grosbachfb12f352011-09-19 18:42:21 +00002907 // If there's a pre-indexing writeback marker, '!', just add it as a token
2908 // operand. It's rather odd, but syntactically valid.
2909 if (Parser.getTok().is(AsmToken::Exclaim)) {
2910 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2911 Parser.Lex(); // Eat the '!'.
2912 }
2913
Jim Grosbach7ce05792011-08-03 23:50:40 +00002914 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002915 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002916
Jim Grosbach7ce05792011-08-03 23:50:40 +00002917 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
2918 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002919
Jim Grosbach7ce05792011-08-03 23:50:40 +00002920 // If we have a '#' it's an immediate offset, else assume it's a register
2921 // offset.
2922 if (Parser.getTok().is(AsmToken::Hash)) {
2923 Parser.Lex(); // Eat the '#'.
2924 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002925
Owen Anderson0da10cf2011-08-29 19:36:44 +00002926 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002927 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002928 if (getParser().ParseExpression(Offset))
2929 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002930
2931 // The expression has to be a constant. Memory references with relocations
2932 // don't come through here, as they use the <label> forms of the relevant
2933 // instructions.
2934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2935 if (!CE)
2936 return Error (E, "constant expression expected");
2937
Owen Anderson0da10cf2011-08-29 19:36:44 +00002938 // If the constant was #-0, represent it as INT32_MIN.
2939 int32_t Val = CE->getValue();
2940 if (isNegative && Val == 0)
2941 CE = MCConstantExpr::Create(INT32_MIN, getContext());
2942
Jim Grosbach7ce05792011-08-03 23:50:40 +00002943 // Now we should have the closing ']'
2944 E = Parser.getTok().getLoc();
2945 if (Parser.getTok().isNot(AsmToken::RBrac))
2946 return Error(E, "']' expected");
2947 Parser.Lex(); // Eat right bracket token.
2948
2949 // Don't worry about range checking the value here. That's handled by
2950 // the is*() predicates.
2951 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
2952 ARM_AM::no_shift, 0, false, S,E));
2953
2954 // If there's a pre-indexing writeback marker, '!', just add it as a token
2955 // operand.
2956 if (Parser.getTok().is(AsmToken::Exclaim)) {
2957 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2958 Parser.Lex(); // Eat the '!'.
2959 }
2960
2961 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002962 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00002963
2964 // The register offset is optionally preceded by a '+' or '-'
2965 bool isNegative = false;
2966 if (Parser.getTok().is(AsmToken::Minus)) {
2967 isNegative = true;
2968 Parser.Lex(); // Eat the '-'.
2969 } else if (Parser.getTok().is(AsmToken::Plus)) {
2970 // Nothing to do.
2971 Parser.Lex(); // Eat the '+'.
2972 }
2973
2974 E = Parser.getTok().getLoc();
2975 int OffsetRegNum = tryParseRegister();
2976 if (OffsetRegNum == -1)
2977 return Error(E, "register expected");
2978
2979 // If there's a shift operator, handle it.
2980 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002981 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002982 if (Parser.getTok().is(AsmToken::Comma)) {
2983 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002984 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00002985 return true;
2986 }
2987
2988 // Now we should have the closing ']'
2989 E = Parser.getTok().getLoc();
2990 if (Parser.getTok().isNot(AsmToken::RBrac))
2991 return Error(E, "']' expected");
2992 Parser.Lex(); // Eat right bracket token.
2993
2994 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002995 ShiftType, ShiftImm, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002996 S, E));
2997
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002998 // If there's a pre-indexing writeback marker, '!', just add it as a token
2999 // operand.
3000 if (Parser.getTok().is(AsmToken::Exclaim)) {
3001 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3002 Parser.Lex(); // Eat the '!'.
3003 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003004
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003005 return false;
3006}
3007
Jim Grosbach7ce05792011-08-03 23:50:40 +00003008/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003009/// ( lsl | lsr | asr | ror ) , # shift_amount
3010/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003011/// return true if it parses a shift otherwise it returns false.
3012bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3013 unsigned &Amount) {
3014 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003015 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003016 if (Tok.isNot(AsmToken::Identifier))
3017 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003018 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003019 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003020 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003021 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003022 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003023 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003024 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003025 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003026 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003027 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003028 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003029 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003030 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003031 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003032
Jim Grosbach7ce05792011-08-03 23:50:40 +00003033 // rrx stands alone.
3034 Amount = 0;
3035 if (St != ARM_AM::rrx) {
3036 Loc = Parser.getTok().getLoc();
3037 // A '#' and a shift amount.
3038 const AsmToken &HashTok = Parser.getTok();
3039 if (HashTok.isNot(AsmToken::Hash))
3040 return Error(HashTok.getLoc(), "'#' expected");
3041 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003042
Jim Grosbach7ce05792011-08-03 23:50:40 +00003043 const MCExpr *Expr;
3044 if (getParser().ParseExpression(Expr))
3045 return true;
3046 // Range check the immediate.
3047 // lsl, ror: 0 <= imm <= 31
3048 // lsr, asr: 0 <= imm <= 32
3049 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3050 if (!CE)
3051 return Error(Loc, "shift amount must be an immediate");
3052 int64_t Imm = CE->getValue();
3053 if (Imm < 0 ||
3054 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3055 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3056 return Error(Loc, "immediate shift value out of range");
3057 Amount = Imm;
3058 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003059
3060 return false;
3061}
3062
Jim Grosbach9d390362011-10-03 23:38:36 +00003063/// parseFPImm - A floating point immediate expression operand.
3064ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3065parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3066 SMLoc S = Parser.getTok().getLoc();
3067
3068 if (Parser.getTok().isNot(AsmToken::Hash))
3069 return MatchOperand_NoMatch;
3070 Parser.Lex(); // Eat the '#'.
3071
3072 // Handle negation, as that still comes through as a separate token.
3073 bool isNegative = false;
3074 if (Parser.getTok().is(AsmToken::Minus)) {
3075 isNegative = true;
3076 Parser.Lex();
3077 }
3078 const AsmToken &Tok = Parser.getTok();
3079 if (Tok.is(AsmToken::Real)) {
3080 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3081 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3082 // If we had a '-' in front, toggle the sign bit.
3083 IntVal ^= (uint64_t)isNegative << 63;
3084 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3085 Parser.Lex(); // Eat the token.
3086 if (Val == -1) {
3087 TokError("floating point value out of range");
3088 return MatchOperand_ParseFail;
3089 }
3090 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3091 return MatchOperand_Success;
3092 }
3093 if (Tok.is(AsmToken::Integer)) {
3094 int64_t Val = Tok.getIntVal();
3095 Parser.Lex(); // Eat the token.
3096 if (Val > 255 || Val < 0) {
3097 TokError("encoded floating point value out of range");
3098 return MatchOperand_ParseFail;
3099 }
3100 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3101 return MatchOperand_Success;
3102 }
3103
3104 TokError("invalid floating point immediate");
3105 return MatchOperand_ParseFail;
3106}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003107/// Parse a arm instruction operand. For now this parses the operand regardless
3108/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003109bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003110 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003111 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003112
3113 // Check if the current operand has a custom associated parser, if so, try to
3114 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003115 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3116 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003117 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003118 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3119 // there was a match, but an error occurred, in which case, just return that
3120 // the operand parsing failed.
3121 if (ResTy == MatchOperand_ParseFail)
3122 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003123
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003124 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003125 default:
3126 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003127 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003128 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003129 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003130 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003131 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003132 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003133 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003134 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003135 else if (Res == -1) // irrecoverable error
3136 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003137 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3138 S = Parser.getTok().getLoc();
3139 Parser.Lex();
3140 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3141 return false;
3142 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003143
3144 // Fall though for the Identifier case that is not a register or a
3145 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003146 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003147 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3148 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003149 // This was not a register so parse other operands that start with an
3150 // identifier (like labels) as expressions and create them as immediates.
3151 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003152 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003153 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003154 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003155 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003156 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3157 return false;
3158 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003159 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003160 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003161 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003162 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003163 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003164 // #42 -> immediate.
3165 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003166 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003167 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003168 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003169 const MCExpr *ImmVal;
3170 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003171 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3173 if (!CE) {
3174 Error(S, "constant expression expected");
3175 return MatchOperand_ParseFail;
3176 }
3177 int32_t Val = CE->getValue();
3178 if (isNegative && Val == 0)
3179 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003180 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003181 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3182 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003183 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003184 case AsmToken::Colon: {
3185 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003186 // FIXME: Check it's an expression prefix,
3187 // e.g. (FOO - :lower16:BAR) isn't legal.
3188 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003189 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003190 return true;
3191
Evan Cheng75972122011-01-13 07:58:56 +00003192 const MCExpr *SubExprVal;
3193 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003194 return true;
3195
Evan Cheng75972122011-01-13 07:58:56 +00003196 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3197 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003198 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003199 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003200 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003201 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003202 }
3203}
3204
Jim Grosbach1355cf12011-07-26 17:10:22 +00003205// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003206// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003207bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003208 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003209
3210 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003211 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003212 Parser.Lex(); // Eat ':'
3213
3214 if (getLexer().isNot(AsmToken::Identifier)) {
3215 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3216 return true;
3217 }
3218
3219 StringRef IDVal = Parser.getTok().getIdentifier();
3220 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003221 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003222 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003223 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003224 } else {
3225 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3226 return true;
3227 }
3228 Parser.Lex();
3229
3230 if (getLexer().isNot(AsmToken::Colon)) {
3231 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3232 return true;
3233 }
3234 Parser.Lex(); // Eat the last ':'
3235 return false;
3236}
3237
Daniel Dunbar352e1482011-01-11 15:59:50 +00003238/// \brief Given a mnemonic, split out possible predication code and carry
3239/// setting letters to form a canonical mnemonic and flags.
3240//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003241// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003242// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003243StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003244 unsigned &PredicationCode,
3245 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003246 unsigned &ProcessorIMod,
3247 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003248 PredicationCode = ARMCC::AL;
3249 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003250 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003251
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003252 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003253 //
3254 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003255 if ((Mnemonic == "movs" && isThumb()) ||
3256 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3257 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3258 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3259 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3260 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3261 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3262 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003263 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003264
Jim Grosbach3f00e312011-07-11 17:09:57 +00003265 // First, split out any predication code. Ignore mnemonics we know aren't
3266 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003267 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003268 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003269 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003270 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003271 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3272 .Case("eq", ARMCC::EQ)
3273 .Case("ne", ARMCC::NE)
3274 .Case("hs", ARMCC::HS)
3275 .Case("cs", ARMCC::HS)
3276 .Case("lo", ARMCC::LO)
3277 .Case("cc", ARMCC::LO)
3278 .Case("mi", ARMCC::MI)
3279 .Case("pl", ARMCC::PL)
3280 .Case("vs", ARMCC::VS)
3281 .Case("vc", ARMCC::VC)
3282 .Case("hi", ARMCC::HI)
3283 .Case("ls", ARMCC::LS)
3284 .Case("ge", ARMCC::GE)
3285 .Case("lt", ARMCC::LT)
3286 .Case("gt", ARMCC::GT)
3287 .Case("le", ARMCC::LE)
3288 .Case("al", ARMCC::AL)
3289 .Default(~0U);
3290 if (CC != ~0U) {
3291 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3292 PredicationCode = CC;
3293 }
Bill Wendling52925b62010-10-29 23:50:21 +00003294 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003295
Daniel Dunbar352e1482011-01-11 15:59:50 +00003296 // Next, determine if we have a carry setting bit. We explicitly ignore all
3297 // the instructions we know end in 's'.
3298 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003299 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003300 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3301 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3302 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003303 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3304 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003305 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3306 CarrySetting = true;
3307 }
3308
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003309 // The "cps" instruction can have a interrupt mode operand which is glued into
3310 // the mnemonic. Check if this is the case, split it and parse the imod op
3311 if (Mnemonic.startswith("cps")) {
3312 // Split out any imod code.
3313 unsigned IMod =
3314 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3315 .Case("ie", ARM_PROC::IE)
3316 .Case("id", ARM_PROC::ID)
3317 .Default(~0U);
3318 if (IMod != ~0U) {
3319 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3320 ProcessorIMod = IMod;
3321 }
3322 }
3323
Jim Grosbach89df9962011-08-26 21:43:41 +00003324 // The "it" instruction has the condition mask on the end of the mnemonic.
3325 if (Mnemonic.startswith("it")) {
3326 ITMask = Mnemonic.slice(2, Mnemonic.size());
3327 Mnemonic = Mnemonic.slice(0, 2);
3328 }
3329
Daniel Dunbar352e1482011-01-11 15:59:50 +00003330 return Mnemonic;
3331}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003332
3333/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3334/// inclusion of carry set or predication code operands.
3335//
3336// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003337void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003338getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003339 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003340 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3341 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003342 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003343 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003344 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003345 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003346 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003347 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003348 Mnemonic == "mla" || Mnemonic == "smlal" ||
3349 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003350 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003351 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003352 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003353
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003354 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3355 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3356 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3357 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003358 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3359 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003360 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003361 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
3362 !isThumb()) ||
3363 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3364 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003365 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003366 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003367 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003368 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003369
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003370 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003371 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003372 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003373 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003374 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003375}
3376
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003377bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3378 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003379 // FIXME: This is all horribly hacky. We really need a better way to deal
3380 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003381
3382 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3383 // another does not. Specifically, the MOVW instruction does not. So we
3384 // special case it here and remove the defaulted (non-setting) cc_out
3385 // operand if that's the instruction we're trying to match.
3386 //
3387 // We do this as post-processing of the explicit operands rather than just
3388 // conditionally adding the cc_out in the first place because we need
3389 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003390 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003391 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3392 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3393 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3394 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003395
3396 // Register-register 'add' for thumb does not have a cc_out operand
3397 // when there are only two register operands.
3398 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3399 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3400 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3401 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3402 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003403 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003404 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3405 // have to check the immediate range here since Thumb2 has a variant
3406 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003407 if (((isThumb() && Mnemonic == "add") ||
3408 (isThumbTwo() && Mnemonic == "sub")) &&
3409 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003410 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3411 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3412 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003413 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3414 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3415 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003416 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003417 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3418 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003419 // selecting via the generic "add" mnemonic, so to know that we
3420 // should remove the cc_out operand, we have to explicitly check that
3421 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003422 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3423 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003424 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3425 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3426 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3427 // Nest conditions rather than one big 'if' statement for readability.
3428 //
3429 // If either register is a high reg, it's either one of the SP
3430 // variants (handled above) or a 32-bit encoding, so we just
3431 // check against T3.
3432 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3433 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3434 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3435 return false;
3436 // If both registers are low, we're in an IT block, and the immediate is
3437 // in range, we should use encoding T1 instead, which has a cc_out.
3438 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003439 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003440 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3441 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3442 return false;
3443
3444 // Otherwise, we use encoding T4, which does not have a cc_out
3445 // operand.
3446 return true;
3447 }
3448
Jim Grosbach64944f42011-09-14 21:00:40 +00003449 // The thumb2 multiply instruction doesn't have a CCOut register, so
3450 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3451 // use the 16-bit encoding or not.
3452 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3453 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3454 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3455 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3456 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3457 // If the registers aren't low regs, the destination reg isn't the
3458 // same as one of the source regs, or the cc_out operand is zero
3459 // outside of an IT block, we have to use the 32-bit encoding, so
3460 // remove the cc_out operand.
3461 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3462 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3463 !inITBlock() ||
3464 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3465 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3466 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3467 static_cast<ARMOperand*>(Operands[4])->getReg())))
3468 return true;
3469
3470
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003471
Jim Grosbachf69c8042011-08-24 21:42:27 +00003472 // Register-register 'add/sub' for thumb does not have a cc_out operand
3473 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3474 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3475 // right, this will result in better diagnostics (which operand is off)
3476 // anyway.
3477 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3478 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003479 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3480 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3481 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3482 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003483
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003484 return false;
3485}
3486
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003487/// Parse an arm instruction mnemonic followed by its operands.
3488bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3489 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3490 // Create the leading tokens for the mnemonic, split by '.' characters.
3491 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003492 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003493
Daniel Dunbar352e1482011-01-11 15:59:50 +00003494 // Split out the predication code and carry setting flag from the mnemonic.
3495 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003496 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003497 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003498 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003499 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003500 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003501
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003502 // In Thumb1, only the branch (B) instruction can be predicated.
3503 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3504 Parser.EatToEndOfStatement();
3505 return Error(NameLoc, "conditional execution not supported in Thumb1");
3506 }
3507
Jim Grosbachffa32252011-07-19 19:13:28 +00003508 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3509
Jim Grosbach89df9962011-08-26 21:43:41 +00003510 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3511 // is the mask as it will be for the IT encoding if the conditional
3512 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3513 // where the conditional bit0 is zero, the instruction post-processing
3514 // will adjust the mask accordingly.
3515 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003516 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3517 if (ITMask.size() > 3) {
3518 Parser.EatToEndOfStatement();
3519 return Error(Loc, "too many conditions on IT instruction");
3520 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003521 unsigned Mask = 8;
3522 for (unsigned i = ITMask.size(); i != 0; --i) {
3523 char pos = ITMask[i - 1];
3524 if (pos != 't' && pos != 'e') {
3525 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003526 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003527 }
3528 Mask >>= 1;
3529 if (ITMask[i - 1] == 't')
3530 Mask |= 8;
3531 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003532 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003533 }
3534
Jim Grosbachffa32252011-07-19 19:13:28 +00003535 // FIXME: This is all a pretty gross hack. We should automatically handle
3536 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003537
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003538 // Next, add the CCOut and ConditionCode operands, if needed.
3539 //
3540 // For mnemonics which can ever incorporate a carry setting bit or predication
3541 // code, our matching model involves us always generating CCOut and
3542 // ConditionCode operands to match the mnemonic "as written" and then we let
3543 // the matcher deal with finding the right instruction or generating an
3544 // appropriate error.
3545 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003546 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003547
Jim Grosbach33c16a22011-07-14 22:04:21 +00003548 // If we had a carry-set on an instruction that can't do that, issue an
3549 // error.
3550 if (!CanAcceptCarrySet && CarrySetting) {
3551 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003552 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003553 "' can not set flags, but 's' suffix specified");
3554 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003555 // If we had a predication code on an instruction that can't do that, issue an
3556 // error.
3557 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3558 Parser.EatToEndOfStatement();
3559 return Error(NameLoc, "instruction '" + Mnemonic +
3560 "' is not predicable, but condition code specified");
3561 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003562
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003563 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003564 if (CanAcceptCarrySet) {
3565 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003566 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003567 Loc));
3568 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003569
3570 // Add the predication code operand, if necessary.
3571 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003572 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3573 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003574 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003575 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003576 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003577
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003578 // Add the processor imod operand, if necessary.
3579 if (ProcessorIMod) {
3580 Operands.push_back(ARMOperand::CreateImm(
3581 MCConstantExpr::Create(ProcessorIMod, getContext()),
3582 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003583 }
3584
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003585 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003586 while (Next != StringRef::npos) {
3587 Start = Next;
3588 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003589 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003590
Jim Grosbach4d23e992011-08-24 22:19:48 +00003591 // For now, we're only parsing Thumb1 (for the most part), so
3592 // just ignore ".n" qualifiers. We'll use them to restrict
3593 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003594 if (ExtraToken != ".n") {
3595 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3596 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3597 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003598 }
3599
3600 // Read the remaining operands.
3601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003602 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003603 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003604 Parser.EatToEndOfStatement();
3605 return true;
3606 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003607
3608 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003609 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003610
3611 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003612 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003613 Parser.EatToEndOfStatement();
3614 return true;
3615 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003616 }
3617 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003618
Chris Lattnercbf8a982010-09-11 16:18:25 +00003619 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3620 Parser.EatToEndOfStatement();
Chris Lattner34e53142010-09-08 05:10:46 +00003621 return TokError("unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003622 }
Bill Wendling146018f2010-11-06 21:42:12 +00003623
Chris Lattner34e53142010-09-08 05:10:46 +00003624 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003625
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003626 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3627 // do and don't have a cc_out optional-def operand. With some spot-checks
3628 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003629 // parse and adjust accordingly before actually matching. We shouldn't ever
3630 // try to remove a cc_out operand that was explicitly set on the the
3631 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3632 // table driven matcher doesn't fit well with the ARM instruction set.
3633 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003634 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3635 Operands.erase(Operands.begin() + 1);
3636 delete Op;
3637 }
3638
Jim Grosbachcf121c32011-07-28 21:57:55 +00003639 // ARM mode 'blx' need special handling, as the register operand version
3640 // is predicable, but the label operand version is not. So, we can't rely
3641 // on the Mnemonic based checking to correctly figure out when to put
3642 // a CondCode operand in the list. If we're trying to match the label
3643 // version, remove the CondCode operand here.
3644 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3645 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3646 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3647 Operands.erase(Operands.begin() + 1);
3648 delete Op;
3649 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003650
3651 // The vector-compare-to-zero instructions have a literal token "#0" at
3652 // the end that comes to here as an immediate operand. Convert it to a
3653 // token to play nicely with the matcher.
3654 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3655 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3656 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3657 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3659 if (CE && CE->getValue() == 0) {
3660 Operands.erase(Operands.begin() + 5);
3661 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3662 delete Op;
3663 }
3664 }
Jim Grosbach68259142011-10-03 22:30:24 +00003665 // VCMP{E} does the same thing, but with a different operand count.
3666 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3667 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3668 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3669 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3670 if (CE && CE->getValue() == 0) {
3671 Operands.erase(Operands.begin() + 4);
3672 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3673 delete Op;
3674 }
3675 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003676 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3677 // end. Convert it to a token here.
3678 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3679 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3680 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3682 if (CE && CE->getValue() == 0) {
3683 Operands.erase(Operands.begin() + 5);
3684 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3685 delete Op;
3686 }
3687 }
3688
Chris Lattner98986712010-01-14 22:21:20 +00003689 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003690}
3691
Jim Grosbach189610f2011-07-26 18:25:39 +00003692// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003693
3694// return 'true' if register list contains non-low GPR registers,
3695// 'false' otherwise. If Reg is in the register list or is HiReg, set
3696// 'containsReg' to true.
3697static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3698 unsigned HiReg, bool &containsReg) {
3699 containsReg = false;
3700 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3701 unsigned OpReg = Inst.getOperand(i).getReg();
3702 if (OpReg == Reg)
3703 containsReg = true;
3704 // Anything other than a low register isn't legal here.
3705 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3706 return true;
3707 }
3708 return false;
3709}
3710
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003711// Check if the specified regisgter is in the register list of the inst,
3712// starting at the indicated operand number.
3713static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3714 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3715 unsigned OpReg = Inst.getOperand(i).getReg();
3716 if (OpReg == Reg)
3717 return true;
3718 }
3719 return false;
3720}
3721
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003722// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3723// the ARMInsts array) instead. Getting that here requires awkward
3724// API changes, though. Better way?
3725namespace llvm {
3726extern MCInstrDesc ARMInsts[];
3727}
3728static MCInstrDesc &getInstDesc(unsigned Opcode) {
3729 return ARMInsts[Opcode];
3730}
3731
Jim Grosbach189610f2011-07-26 18:25:39 +00003732// FIXME: We would really like to be able to tablegen'erate this.
3733bool ARMAsmParser::
3734validateInstruction(MCInst &Inst,
3735 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003736 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3737 SMLoc Loc = Operands[0]->getStartLoc();
3738 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00003739 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3740 // being allowed in IT blocks, but not being predicable. It just always
3741 // executes.
3742 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003743 unsigned bit = 1;
3744 if (ITState.FirstCond)
3745 ITState.FirstCond = false;
3746 else
Jim Grosbacha1109882011-09-02 23:22:08 +00003747 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003748 // The instruction must be predicable.
3749 if (!MCID.isPredicable())
3750 return Error(Loc, "instructions in IT block must be predicable");
3751 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3752 unsigned ITCond = bit ? ITState.Cond :
3753 ARMCC::getOppositeCondition(ITState.Cond);
3754 if (Cond != ITCond) {
3755 // Find the condition code Operand to get its SMLoc information.
3756 SMLoc CondLoc;
3757 for (unsigned i = 1; i < Operands.size(); ++i)
3758 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3759 CondLoc = Operands[i]->getStartLoc();
3760 return Error(CondLoc, "incorrect condition in IT block; got '" +
3761 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3762 "', but expected '" +
3763 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3764 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00003765 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003766 } else if (isThumbTwo() && MCID.isPredicable() &&
3767 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003768 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3769 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003770 return Error(Loc, "predicated instructions must be in IT block");
3771
Jim Grosbach189610f2011-07-26 18:25:39 +00003772 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003773 case ARM::LDRD:
3774 case ARM::LDRD_PRE:
3775 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003776 case ARM::LDREXD: {
3777 // Rt2 must be Rt + 1.
3778 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3779 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3780 if (Rt2 != Rt + 1)
3781 return Error(Operands[3]->getStartLoc(),
3782 "destination operands must be sequential");
3783 return false;
3784 }
Jim Grosbach14605d12011-08-11 20:28:23 +00003785 case ARM::STRD: {
3786 // Rt2 must be Rt + 1.
3787 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3788 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3789 if (Rt2 != Rt + 1)
3790 return Error(Operands[3]->getStartLoc(),
3791 "source operands must be sequential");
3792 return false;
3793 }
Jim Grosbach53642c52011-08-10 20:49:18 +00003794 case ARM::STRD_PRE:
3795 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003796 case ARM::STREXD: {
3797 // Rt2 must be Rt + 1.
3798 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3799 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
3800 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00003801 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00003802 "source operands must be sequential");
3803 return false;
3804 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003805 case ARM::SBFX:
3806 case ARM::UBFX: {
3807 // width must be in range [1, 32-lsb]
3808 unsigned lsb = Inst.getOperand(2).getImm();
3809 unsigned widthm1 = Inst.getOperand(3).getImm();
3810 if (widthm1 >= 32 - lsb)
3811 return Error(Operands[5]->getStartLoc(),
3812 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00003813 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003814 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003815 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003816 // If we're parsing Thumb2, the .w variant is available and handles
3817 // most cases that are normally illegal for a Thumb1 LDM
3818 // instruction. We'll make the transformation in processInstruction()
3819 // if necessary.
3820 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003821 // Thumb LDM instructions are writeback iff the base register is not
3822 // in the register list.
3823 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00003824 bool hasWritebackToken =
3825 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3826 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00003827 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003828 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00003829 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
3830 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003831 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003832 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003833 return Error(Operands[2]->getStartLoc(),
3834 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003835 // If we should not have writeback, there must not be a '!'. This is
3836 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003837 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00003838 return Error(Operands[3]->getStartLoc(),
3839 "writeback operator '!' not allowed when base register "
3840 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003841
3842 break;
3843 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003844 case ARM::t2LDMIA_UPD: {
3845 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
3846 return Error(Operands[4]->getStartLoc(),
3847 "writeback operator '!' not allowed when base register "
3848 "in register list");
3849 break;
3850 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003851 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00003852 bool listContainsBase;
3853 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
3854 return Error(Operands[2]->getStartLoc(),
3855 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003856 break;
3857 }
3858 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00003859 bool listContainsBase;
3860 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
3861 return Error(Operands[2]->getStartLoc(),
3862 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003863 break;
3864 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00003865 case ARM::tSTMIA_UPD: {
3866 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00003867 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00003868 return Error(Operands[4]->getStartLoc(),
3869 "registers must be in range r0-r7");
3870 break;
3871 }
Jim Grosbach189610f2011-07-26 18:25:39 +00003872 }
3873
3874 return false;
3875}
3876
Jim Grosbachf8fce712011-08-11 17:35:48 +00003877void ARMAsmParser::
3878processInstruction(MCInst &Inst,
3879 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3880 switch (Inst.getOpcode()) {
3881 case ARM::LDMIA_UPD:
3882 // If this is a load of a single register via a 'pop', then we should use
3883 // a post-indexed LDR instruction instead, per the ARM ARM.
3884 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
3885 Inst.getNumOperands() == 5) {
3886 MCInst TmpInst;
3887 TmpInst.setOpcode(ARM::LDR_POST_IMM);
3888 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3889 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3890 TmpInst.addOperand(Inst.getOperand(1)); // Rn
3891 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
3892 TmpInst.addOperand(MCOperand::CreateImm(4));
3893 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3894 TmpInst.addOperand(Inst.getOperand(3));
3895 Inst = TmpInst;
3896 }
3897 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00003898 case ARM::STMDB_UPD:
3899 // If this is a store of a single register via a 'push', then we should use
3900 // a pre-indexed STR instruction instead, per the ARM ARM.
3901 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
3902 Inst.getNumOperands() == 5) {
3903 MCInst TmpInst;
3904 TmpInst.setOpcode(ARM::STR_PRE_IMM);
3905 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3906 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3907 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
3908 TmpInst.addOperand(MCOperand::CreateImm(-4));
3909 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3910 TmpInst.addOperand(Inst.getOperand(3));
3911 Inst = TmpInst;
3912 }
3913 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00003914 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00003915 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3916 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3917 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3918 // to encoding T1 if <Rd> is omitted."
3919 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00003920 Inst.setOpcode(ARM::tADDi3);
3921 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003922 case ARM::tSUBi8:
3923 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3924 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3925 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3926 // to encoding T1 if <Rd> is omitted."
3927 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
3928 Inst.setOpcode(ARM::tSUBi3);
3929 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003930 case ARM::tB:
3931 // A Thumb conditional branch outside of an IT block is a tBcc.
3932 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3933 Inst.setOpcode(ARM::tBcc);
3934 break;
3935 case ARM::t2B:
3936 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
3937 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3938 Inst.setOpcode(ARM::t2Bcc);
3939 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00003940 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00003941 // If the conditional is AL or we're in an IT block, we really want t2B.
3942 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00003943 Inst.setOpcode(ARM::t2B);
3944 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00003945 case ARM::tBcc:
3946 // If the conditional is AL, we really want tB.
3947 if (Inst.getOperand(1).getImm() == ARMCC::AL)
3948 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00003949 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003950 case ARM::tLDMIA: {
3951 // If the register list contains any high registers, or if the writeback
3952 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
3953 // instead if we're in Thumb2. Otherwise, this should have generated
3954 // an error in validateInstruction().
3955 unsigned Rn = Inst.getOperand(0).getReg();
3956 bool hasWritebackToken =
3957 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3958 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
3959 bool listContainsBase;
3960 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
3961 (!listContainsBase && !hasWritebackToken) ||
3962 (listContainsBase && hasWritebackToken)) {
3963 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3964 assert (isThumbTwo());
3965 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
3966 // If we're switching to the updating version, we need to insert
3967 // the writeback tied operand.
3968 if (hasWritebackToken)
3969 Inst.insert(Inst.begin(),
3970 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
3971 }
3972 break;
3973 }
Jim Grosbach8213c962011-09-16 20:50:13 +00003974 case ARM::tSTMIA_UPD: {
3975 // If the register list contains any high registers, we need to use
3976 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
3977 // should have generated an error in validateInstruction().
3978 unsigned Rn = Inst.getOperand(0).getReg();
3979 bool listContainsBase;
3980 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
3981 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3982 assert (isThumbTwo());
3983 Inst.setOpcode(ARM::t2STMIA_UPD);
3984 }
3985 break;
3986 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003987 case ARM::t2MOVi: {
3988 // If we can use the 16-bit encoding and the user didn't explicitly
3989 // request the 32-bit variant, transform it here.
3990 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
3991 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00003992 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
3993 Inst.getOperand(4).getReg() == ARM::CPSR) ||
3994 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003995 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
3996 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
3997 // The operands aren't in the same order for tMOVi8...
3998 MCInst TmpInst;
3999 TmpInst.setOpcode(ARM::tMOVi8);
4000 TmpInst.addOperand(Inst.getOperand(0));
4001 TmpInst.addOperand(Inst.getOperand(4));
4002 TmpInst.addOperand(Inst.getOperand(1));
4003 TmpInst.addOperand(Inst.getOperand(2));
4004 TmpInst.addOperand(Inst.getOperand(3));
4005 Inst = TmpInst;
4006 }
4007 break;
4008 }
4009 case ARM::t2MOVr: {
4010 // If we can use the 16-bit encoding and the user didn't explicitly
4011 // request the 32-bit variant, transform it here.
4012 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4013 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4014 Inst.getOperand(2).getImm() == ARMCC::AL &&
4015 Inst.getOperand(4).getReg() == ARM::CPSR &&
4016 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4017 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4018 // The operands aren't the same for tMOV[S]r... (no cc_out)
4019 MCInst TmpInst;
4020 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4021 TmpInst.addOperand(Inst.getOperand(0));
4022 TmpInst.addOperand(Inst.getOperand(1));
4023 TmpInst.addOperand(Inst.getOperand(2));
4024 TmpInst.addOperand(Inst.getOperand(3));
4025 Inst = TmpInst;
4026 }
4027 break;
4028 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004029 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004030 case ARM::t2SXTB:
4031 case ARM::t2UXTH:
4032 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004033 // If we can use the 16-bit encoding and the user didn't explicitly
4034 // request the 32-bit variant, transform it here.
4035 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4036 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4037 Inst.getOperand(2).getImm() == 0 &&
4038 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4039 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004040 unsigned NewOpc;
4041 switch (Inst.getOpcode()) {
4042 default: llvm_unreachable("Illegal opcode!");
4043 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4044 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4045 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4046 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4047 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004048 // The operands aren't the same for thumb1 (no rotate operand).
4049 MCInst TmpInst;
4050 TmpInst.setOpcode(NewOpc);
4051 TmpInst.addOperand(Inst.getOperand(0));
4052 TmpInst.addOperand(Inst.getOperand(1));
4053 TmpInst.addOperand(Inst.getOperand(3));
4054 TmpInst.addOperand(Inst.getOperand(4));
4055 Inst = TmpInst;
4056 }
4057 break;
4058 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004059 case ARM::t2IT: {
4060 // The mask bits for all but the first condition are represented as
4061 // the low bit of the condition code value implies 't'. We currently
4062 // always have 1 implies 't', so XOR toggle the bits if the low bit
4063 // of the condition code is zero. The encoding also expects the low
4064 // bit of the condition to be encoded as bit 4 of the mask operand,
4065 // so mask that in if needed
4066 MCOperand &MO = Inst.getOperand(1);
4067 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004068 unsigned OrigMask = Mask;
4069 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004070 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004071 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4072 for (unsigned i = 3; i != TZ; --i)
4073 Mask ^= 1 << i;
4074 } else
4075 Mask |= 0x10;
4076 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004077
4078 // Set up the IT block state according to the IT instruction we just
4079 // matched.
4080 assert(!inITBlock() && "nested IT blocks?!");
4081 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4082 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4083 ITState.CurPosition = 0;
4084 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004085 break;
4086 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004087 }
4088}
4089
Jim Grosbach47a0d522011-08-16 20:45:50 +00004090unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4091 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4092 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004093 unsigned Opc = Inst.getOpcode();
4094 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004095 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4096 assert(MCID.hasOptionalDef() &&
4097 "optionally flag setting instruction missing optional def operand");
4098 assert(MCID.NumOperands == Inst.getNumOperands() &&
4099 "operand count mismatch!");
4100 // Find the optional-def operand (cc_out).
4101 unsigned OpNo;
4102 for (OpNo = 0;
4103 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4104 ++OpNo)
4105 ;
4106 // If we're parsing Thumb1, reject it completely.
4107 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4108 return Match_MnemonicFail;
4109 // If we're parsing Thumb2, which form is legal depends on whether we're
4110 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004111 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4112 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004113 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004114 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4115 inITBlock())
4116 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004117 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004118 // Some high-register supporting Thumb1 encodings only allow both registers
4119 // to be from r0-r7 when in Thumb2.
4120 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4121 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4122 isARMLowRegister(Inst.getOperand(2).getReg()))
4123 return Match_RequiresThumb2;
4124 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004125 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004126 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4127 isARMLowRegister(Inst.getOperand(1).getReg()))
4128 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004129 return Match_Success;
4130}
4131
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004132bool ARMAsmParser::
4133MatchAndEmitInstruction(SMLoc IDLoc,
4134 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4135 MCStreamer &Out) {
4136 MCInst Inst;
4137 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004138 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004139 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004140 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004141 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004142 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004143 // Context sensitive operand constraints aren't handled by the matcher,
4144 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004145 if (validateInstruction(Inst, Operands)) {
4146 // Still progress the IT block, otherwise one wrong condition causes
4147 // nasty cascading errors.
4148 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004149 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004150 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004151
Jim Grosbachf8fce712011-08-11 17:35:48 +00004152 // Some instructions need post-processing to, for example, tweak which
4153 // encoding is selected.
4154 processInstruction(Inst, Operands);
4155
Jim Grosbacha1109882011-09-02 23:22:08 +00004156 // Only move forward at the very end so that everything in validate
4157 // and process gets a consistent answer about whether we're in an IT
4158 // block.
4159 forwardITPosition();
4160
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004161 Out.EmitInstruction(Inst);
4162 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004163 case Match_MissingFeature:
4164 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4165 return true;
4166 case Match_InvalidOperand: {
4167 SMLoc ErrorLoc = IDLoc;
4168 if (ErrorInfo != ~0U) {
4169 if (ErrorInfo >= Operands.size())
4170 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004171
Chris Lattnere73d4f82010-10-28 21:41:58 +00004172 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4173 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4174 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004175
Chris Lattnere73d4f82010-10-28 21:41:58 +00004176 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004177 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004178 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004179 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004180 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004181 // The converter function will have already emited a diagnostic.
4182 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004183 case Match_RequiresNotITBlock:
4184 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004185 case Match_RequiresITBlock:
4186 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004187 case Match_RequiresV6:
4188 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4189 case Match_RequiresThumb2:
4190 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004191 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004192
Eric Christopherc223e2b2010-10-29 09:26:59 +00004193 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004194 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004195}
4196
Jim Grosbach1355cf12011-07-26 17:10:22 +00004197/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004198bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4199 StringRef IDVal = DirectiveID.getIdentifier();
4200 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004201 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004202 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004203 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004204 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004205 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004206 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004207 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004208 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004209 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004210 return true;
4211}
4212
Jim Grosbach1355cf12011-07-26 17:10:22 +00004213/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004214/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004215bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004216 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4217 for (;;) {
4218 const MCExpr *Value;
4219 if (getParser().ParseExpression(Value))
4220 return true;
4221
Chris Lattneraaec2052010-01-19 19:46:13 +00004222 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004223
4224 if (getLexer().is(AsmToken::EndOfStatement))
4225 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004227 // FIXME: Improve diagnostic.
4228 if (getLexer().isNot(AsmToken::Comma))
4229 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004230 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004231 }
4232 }
4233
Sean Callananb9a25b72010-01-19 20:27:46 +00004234 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004235 return false;
4236}
4237
Jim Grosbach1355cf12011-07-26 17:10:22 +00004238/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004239/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004240bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004241 if (getLexer().isNot(AsmToken::EndOfStatement))
4242 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004243 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004244
4245 // TODO: set thumb mode
4246 // TODO: tell the MC streamer the mode
4247 // getParser().getStreamer().Emit???();
4248 return false;
4249}
4250
Jim Grosbach1355cf12011-07-26 17:10:22 +00004251/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004252/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004253bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004254 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4255 bool isMachO = MAI.hasSubsectionsViaSymbols();
4256 StringRef Name;
4257
4258 // Darwin asm has function name after .thumb_func direction
4259 // ELF doesn't
4260 if (isMachO) {
4261 const AsmToken &Tok = Parser.getTok();
4262 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4263 return Error(L, "unexpected token in .thumb_func directive");
4264 Name = Tok.getString();
4265 Parser.Lex(); // Consume the identifier token.
4266 }
4267
Kevin Enderby515d5092009-10-15 20:48:48 +00004268 if (getLexer().isNot(AsmToken::EndOfStatement))
4269 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004270 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004271
Rafael Espindola64695402011-05-16 16:17:21 +00004272 // FIXME: assuming function name will be the line following .thumb_func
4273 if (!isMachO) {
4274 Name = Parser.getTok().getString();
4275 }
4276
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004277 // Mark symbol as a thumb symbol.
4278 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4279 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004280 return false;
4281}
4282
Jim Grosbach1355cf12011-07-26 17:10:22 +00004283/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004284/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004285bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004286 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004287 if (Tok.isNot(AsmToken::Identifier))
4288 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004289 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004290 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004291 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004292 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004293 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004294 else
4295 return Error(L, "unrecognized syntax mode in .syntax directive");
4296
4297 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004298 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004299 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004300
4301 // TODO tell the MC streamer the mode
4302 // getParser().getStreamer().Emit???();
4303 return false;
4304}
4305
Jim Grosbach1355cf12011-07-26 17:10:22 +00004306/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004307/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004308bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004309 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004310 if (Tok.isNot(AsmToken::Integer))
4311 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004312 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004313 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004314 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004315 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004316 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004317 else
4318 return Error(L, "invalid operand to .code directive");
4319
4320 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004321 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004322 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004323
Evan Cheng32869202011-07-08 22:36:29 +00004324 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004325 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004326 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004327 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004328 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004329 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004330 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004331 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004332 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004333
Kevin Enderby515d5092009-10-15 20:48:48 +00004334 return false;
4335}
4336
Sean Callanan90b70972010-04-07 20:29:34 +00004337extern "C" void LLVMInitializeARMAsmLexer();
4338
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004339/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004340extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004341 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4342 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004343 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004344}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004345
Chris Lattner0692ee62010-09-06 19:11:01 +00004346#define GET_REGISTER_MATCHER
4347#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004348#include "ARMGenAsmMatcher.inc"