blob: 4552374bcc7d17a86e211211b28ac010fc7f531d [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
10#include "ARM.h"
Daniel Dunbar3483aca2010-08-11 05:24:50 +000011#include "ARMSubtarget.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000012#include "llvm/MC/MCParser/MCAsmLexer.h"
13#include "llvm/MC/MCParser/MCAsmParser.h"
14#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000015#include "llvm/MC/MCStreamer.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/Target/TargetRegistry.h"
19#include "llvm/Target/TargetAsmParser.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000020#include "llvm/Support/SourceMgr.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000021#include "llvm/Support/raw_ostream.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000022#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000023#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000024#include "llvm/ADT/Twine.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000025using namespace llvm;
26
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000027// The shift types for register controlled shifts in arm memory addressing
28enum ShiftType {
29 Lsl,
30 Lsr,
31 Asr,
32 Ror,
33 Rrx
34};
35
Chris Lattner3a697562010-10-28 17:20:03 +000036namespace {
37 struct ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000038
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000039class ARMAsmParser : public TargetAsmParser {
40 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000041 TargetMachine &TM;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000042
43private:
44 MCAsmParser &getParser() const { return Parser; }
45
46 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
47
48 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
49
50 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
51
Chris Lattnere5658fa2010-10-30 04:09:10 +000052 int TryParseRegister();
53 ARMOperand *TryParseRegisterWithWriteBack();
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +000054 ARMOperand *ParseRegisterList();
Chris Lattner550276e2010-10-28 20:52:15 +000055 ARMOperand *ParseMemory();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000056
Kevin Enderby9c41fa82009-10-30 22:55:57 +000057 bool ParseMemoryOffsetReg(bool &Negative,
58 bool &OffsetRegShifted,
59 enum ShiftType &ShiftType,
60 const MCExpr *&ShiftAmount,
61 const MCExpr *&Offset,
62 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +000063 int &OffsetRegNum,
64 SMLoc &E);
Kevin Enderby9c41fa82009-10-30 22:55:57 +000065
Sean Callanan76264762010-04-02 22:27:05 +000066 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000067
Chris Lattner550276e2010-10-28 20:52:15 +000068 ARMOperand *ParseOperand();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000069
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000070 bool ParseDirectiveWord(unsigned Size, SMLoc L);
71
Kevin Enderby515d5092009-10-15 20:48:48 +000072 bool ParseDirectiveThumb(SMLoc L);
73
74 bool ParseDirectiveThumbFunc(SMLoc L);
75
76 bool ParseDirectiveCode(SMLoc L);
77
78 bool ParseDirectiveSyntax(SMLoc L);
79
Chris Lattner7036f8b2010-09-29 01:42:58 +000080 bool MatchAndEmitInstruction(SMLoc IDLoc,
Chris Lattner7c51a312010-09-29 01:50:45 +000081 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chris Lattnerfa42fad2010-10-28 21:28:01 +000082 MCStreamer &Out);
Jim Grosbach16c74252010-10-29 14:46:02 +000083
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000084 /// @name Auto-generated Match Functions
85 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +000086
Chris Lattner0692ee62010-09-06 19:11:01 +000087#define GET_ASSEMBLER_HEADER
88#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000089
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000090 /// }
91
92
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000093public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000094 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
Jim Grosbach833c93c2010-11-01 16:59:54 +000095 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
96 // Initialize the set of available features.
97 setAvailableFeatures(ComputeAvailableFeatures(
98 &TM.getSubtarget<ARMSubtarget>()));
99 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000100
Benjamin Kramer38e59892010-07-14 22:38:02 +0000101 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000102 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000103
104 virtual bool ParseDirective(AsmToken DirectiveID);
105};
Jim Grosbach16c74252010-10-29 14:46:02 +0000106} // end anonymous namespace
107
Chris Lattner3a697562010-10-28 17:20:03 +0000108namespace {
109
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000110/// ARMOperand - Instances of this class represent a parsed ARM machine
111/// instruction.
Chris Lattner76593892010-01-14 21:21:40 +0000112struct ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000113public:
114 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000115 CondCode,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000116 Immediate,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000117 Memory,
118 Register,
119 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000120 } Kind;
121
Sean Callanan76264762010-04-02 22:27:05 +0000122 SMLoc StartLoc, EndLoc;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000123
124 union {
125 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000126 ARMCC::CondCodes Val;
127 } CC;
128
129 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000130 const char *Data;
131 unsigned Length;
132 } Tok;
133
134 struct {
135 unsigned RegNum;
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000136 bool Writeback;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 } Reg;
138
Kevin Enderbycfe07242009-10-13 22:19:02 +0000139 struct {
140 const MCExpr *Val;
141 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 // This is for all forms of ARM address expressions
144 struct {
145 unsigned BaseRegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000146 unsigned OffsetRegNum; // used when OffsetIsReg is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000147 const MCExpr *Offset; // used when OffsetIsReg is false
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000148 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000149 enum ShiftType ShiftType; // used when OffsetRegShifted is true
150 unsigned
151 OffsetRegShifted : 1, // only used when OffsetIsReg is true
152 Preindexed : 1,
153 Postindexed : 1,
154 OffsetIsReg : 1,
155 Negative : 1, // only used when OffsetIsReg is true
156 Writeback : 1;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000157 } Mem;
158
159 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000160
Sean Callanan76264762010-04-02 22:27:05 +0000161 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
162 Kind = o.Kind;
163 StartLoc = o.StartLoc;
164 EndLoc = o.EndLoc;
165 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000166 case CondCode:
167 CC = o.CC;
168 break;
Sean Callanan76264762010-04-02 22:27:05 +0000169 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000170 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000171 break;
172 case Register:
173 Reg = o.Reg;
174 break;
175 case Immediate:
176 Imm = o.Imm;
177 break;
178 case Memory:
179 Mem = o.Mem;
180 break;
181 }
182 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000183
Sean Callanan76264762010-04-02 22:27:05 +0000184 /// getStartLoc - Get the location of the first token of this operand.
185 SMLoc getStartLoc() const { return StartLoc; }
186 /// getEndLoc - Get the location of the last token of this operand.
187 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000188
Daniel Dunbar8462b302010-08-11 06:36:53 +0000189 ARMCC::CondCodes getCondCode() const {
190 assert(Kind == CondCode && "Invalid access!");
191 return CC.Val;
192 }
193
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000194 StringRef getToken() const {
195 assert(Kind == Token && "Invalid access!");
196 return StringRef(Tok.Data, Tok.Length);
197 }
198
199 unsigned getReg() const {
200 assert(Kind == Register && "Invalid access!");
201 return Reg.RegNum;
202 }
203
Kevin Enderbycfe07242009-10-13 22:19:02 +0000204 const MCExpr *getImm() const {
205 assert(Kind == Immediate && "Invalid access!");
206 return Imm.Val;
207 }
208
Daniel Dunbar8462b302010-08-11 06:36:53 +0000209 bool isCondCode() const { return Kind == CondCode; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000210 bool isImm() const { return Kind == Immediate; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000211 bool isReg() const { return Kind == Register; }
Chris Lattner14b93852010-10-29 00:27:31 +0000212 bool isToken() const { return Kind == Token; }
213 bool isMemory() const { return Kind == Memory; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000214
215 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000216 // Add as immediates when possible. Null MCExpr = 0.
217 if (Expr == 0)
218 Inst.addOperand(MCOperand::CreateImm(0));
219 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000220 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
221 else
222 Inst.addOperand(MCOperand::CreateExpr(Expr));
223 }
224
Daniel Dunbar8462b302010-08-11 06:36:53 +0000225 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000226 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000227 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000228 // FIXME: What belongs here?
229 Inst.addOperand(MCOperand::CreateReg(0));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000230 }
231
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000232 void addRegOperands(MCInst &Inst, unsigned N) const {
233 assert(N == 1 && "Invalid number of operands!");
234 Inst.addOperand(MCOperand::CreateReg(getReg()));
235 }
236
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000237 void addImmOperands(MCInst &Inst, unsigned N) const {
238 assert(N == 1 && "Invalid number of operands!");
239 addExpr(Inst, getImm());
240 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000241
242
Chris Lattner14b93852010-10-29 00:27:31 +0000243 bool isMemMode5() const {
Chris Lattner14b93852010-10-29 00:27:31 +0000244 if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
Jim Grosbach80eb2332010-10-29 17:41:25 +0000245 Mem.Writeback || Mem.Negative)
Chris Lattner14b93852010-10-29 00:27:31 +0000246 return false;
Jim Grosbach80eb2332010-10-29 17:41:25 +0000247 // If there is an offset expression, make sure it's valid.
248 if (!Mem.Offset)
249 return true;
250 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
251 if (!CE)
252 return false;
253 // The offset must be a multiple of 4 in the range 0-1020.
254 int64_t Value = CE->getValue();
255 return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
Chris Lattner14b93852010-10-29 00:27:31 +0000256 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000257
Chris Lattner14b93852010-10-29 00:27:31 +0000258 void addMemMode5Operands(MCInst &Inst, unsigned N) const {
259 assert(N == 2 && isMemMode5() && "Invalid number of operands!");
Jim Grosbach16c74252010-10-29 14:46:02 +0000260
Chris Lattner14b93852010-10-29 00:27:31 +0000261 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
262 assert(!Mem.OffsetIsReg && "invalid mode 5 operand");
Jim Grosbach80eb2332010-10-29 17:41:25 +0000263 // FIXME: #-0 is encoded differently than #0. Does the parser preserve
264 // the difference?
265 if (Mem.Offset) {
266 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
Jim Grosbach4aaf59d2010-10-30 12:59:16 +0000267 assert(CE && "non-constant mode 5 offset operand!");
Jim Grosbach80eb2332010-10-29 17:41:25 +0000268 // The MCInst offset operand doesn't include the low two bits (like
269 // the instruction encoding).
270 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
271 } else
272 Inst.addOperand(MCOperand::CreateImm(0));
Chris Lattner14b93852010-10-29 00:27:31 +0000273 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000274
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000275 virtual void dump(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000276
Chris Lattner3a697562010-10-28 17:20:03 +0000277 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
278 ARMOperand *Op = new ARMOperand(CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000279 Op->CC.Val = CC;
280 Op->StartLoc = S;
281 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +0000282 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000283 }
284
Chris Lattner3a697562010-10-28 17:20:03 +0000285 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
286 ARMOperand *Op = new ARMOperand(Token);
Sean Callanan76264762010-04-02 22:27:05 +0000287 Op->Tok.Data = Str.data();
288 Op->Tok.Length = Str.size();
289 Op->StartLoc = S;
290 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +0000291 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000292 }
293
Chris Lattner3a697562010-10-28 17:20:03 +0000294 static ARMOperand *CreateReg(unsigned RegNum, bool Writeback, SMLoc S,
295 SMLoc E) {
296 ARMOperand *Op = new ARMOperand(Register);
Sean Callanan76264762010-04-02 22:27:05 +0000297 Op->Reg.RegNum = RegNum;
298 Op->Reg.Writeback = Writeback;
Sean Callanan76264762010-04-02 22:27:05 +0000299 Op->StartLoc = S;
300 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +0000301 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000302 }
303
Chris Lattner3a697562010-10-28 17:20:03 +0000304 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
305 ARMOperand *Op = new ARMOperand(Immediate);
Sean Callanan76264762010-04-02 22:27:05 +0000306 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +0000307 Op->StartLoc = S;
308 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +0000309 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +0000310 }
311
Chris Lattner3a697562010-10-28 17:20:03 +0000312 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
313 const MCExpr *Offset, unsigned OffsetRegNum,
314 bool OffsetRegShifted, enum ShiftType ShiftType,
315 const MCExpr *ShiftAmount, bool Preindexed,
316 bool Postindexed, bool Negative, bool Writeback,
317 SMLoc S, SMLoc E) {
318 ARMOperand *Op = new ARMOperand(Memory);
Sean Callanan76264762010-04-02 22:27:05 +0000319 Op->Mem.BaseRegNum = BaseRegNum;
320 Op->Mem.OffsetIsReg = OffsetIsReg;
321 Op->Mem.Offset = Offset;
322 Op->Mem.OffsetRegNum = OffsetRegNum;
323 Op->Mem.OffsetRegShifted = OffsetRegShifted;
324 Op->Mem.ShiftType = ShiftType;
325 Op->Mem.ShiftAmount = ShiftAmount;
326 Op->Mem.Preindexed = Preindexed;
327 Op->Mem.Postindexed = Postindexed;
328 Op->Mem.Negative = Negative;
329 Op->Mem.Writeback = Writeback;
Jim Grosbach16c74252010-10-29 14:46:02 +0000330
Sean Callanan76264762010-04-02 22:27:05 +0000331 Op->StartLoc = S;
332 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +0000333 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000334 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000335
Chris Lattner3a697562010-10-28 17:20:03 +0000336private:
337 ARMOperand(KindTy K) : Kind(K) {}
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000338};
339
340} // end anonymous namespace.
341
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000342void ARMOperand::dump(raw_ostream &OS) const {
343 switch (Kind) {
344 case CondCode:
345 OS << ARMCondCodeToString(getCondCode());
346 break;
347 case Immediate:
348 getImm()->print(OS);
349 break;
350 case Memory:
351 OS << "<memory>";
352 break;
353 case Register:
354 OS << "<register " << getReg() << ">";
355 break;
356 case Token:
357 OS << "'" << getToken() << "'";
358 break;
359 }
360}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000361
362/// @name Auto-generated Match Functions
363/// {
364
365static unsigned MatchRegisterName(StringRef Name);
366
367/// }
368
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000369/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +0000370/// and if it is a register name the token is eaten and the register number is
371/// returned. Otherwise return -1.
372///
373int ARMAsmParser::TryParseRegister() {
374 const AsmToken &Tok = Parser.getTok();
375 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
Jim Grosbachd4462a52010-11-01 16:44:21 +0000376
Chris Lattnere5658fa2010-10-30 04:09:10 +0000377 // FIXME: Validate register for the current architecture; we have to do
378 // validation later, so maybe there is no need for this here.
379 int RegNum = MatchRegisterName(Tok.getString());
380 if (RegNum == -1)
381 return -1;
382 Parser.Lex(); // Eat identifier token.
383 return RegNum;
384}
Jim Grosbachd4462a52010-11-01 16:44:21 +0000385
386
Chris Lattnere5658fa2010-10-30 04:09:10 +0000387/// Try to parse a register name. The token must be an Identifier when called,
388/// and if it is a register name the token is eaten and the register number is
389/// returned. Otherwise return -1.
Chris Lattner3a697562010-10-28 17:20:03 +0000390///
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000391/// TODO this is likely to change to allow different register types and or to
392/// parse for a specific register type.
Chris Lattnere5658fa2010-10-30 04:09:10 +0000393ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
394 SMLoc S = Parser.getTok().getLoc();
395 int RegNo = TryParseRegister();
396 if (RegNo == -1) return 0;
Jim Grosbachd4462a52010-11-01 16:44:21 +0000397
Chris Lattnere5658fa2010-10-30 04:09:10 +0000398 SMLoc E = Parser.getTok().getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000400 bool Writeback = false;
Chris Lattnere5658fa2010-10-30 04:09:10 +0000401 const AsmToken &ExclaimTok = Parser.getTok();
402 if (ExclaimTok.is(AsmToken::Exclaim)) {
403 E = ExclaimTok.getLoc();
404 Writeback = true;
405 Parser.Lex(); // Eat exclaim token
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000406 }
407
Chris Lattnere5658fa2010-10-30 04:09:10 +0000408 return ARMOperand::CreateReg(RegNo, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000409}
410
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000411/// Parse a register list, return it if successful else return null. The first
412/// token must be a '{' when called.
413ARMOperand *ARMAsmParser::ParseRegisterList() {
Sean Callanan76264762010-04-02 22:27:05 +0000414 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000415 assert(Parser.getTok().is(AsmToken::LCurly) &&
Kevin Enderbycfe07242009-10-13 22:19:02 +0000416 "Token is not an Left Curly Brace");
Sean Callanan76264762010-04-02 22:27:05 +0000417 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000418 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000419
Sean Callanan18b83232010-01-19 21:44:56 +0000420 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000421 SMLoc RegLoc = RegTok.getLoc();
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000422 if (RegTok.isNot(AsmToken::Identifier)) {
423 Error(RegLoc, "register expected");
424 return 0;
425 }
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000426 int RegNum = MatchRegisterName(RegTok.getString());
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000427 if (RegNum == -1) {
428 Error(RegLoc, "register expected");
429 return 0;
430 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000431
Sean Callananb9a25b72010-01-19 20:27:46 +0000432 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000433 unsigned RegList = 1 << RegNum;
434
435 int HighRegNum = RegNum;
436 // TODO ranges like "{Rn-Rm}"
Sean Callanan18b83232010-01-19 21:44:56 +0000437 while (Parser.getTok().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000438 Parser.Lex(); // Eat comma token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000439
Sean Callanan18b83232010-01-19 21:44:56 +0000440 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000441 SMLoc RegLoc = RegTok.getLoc();
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000442 if (RegTok.isNot(AsmToken::Identifier)) {
443 Error(RegLoc, "register expected");
444 return 0;
445 }
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000446 int RegNum = MatchRegisterName(RegTok.getString());
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000447 if (RegNum == -1) {
448 Error(RegLoc, "register expected");
449 return 0;
450 }
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000451
452 if (RegList & (1 << RegNum))
453 Warning(RegLoc, "register duplicated in register list");
454 else if (RegNum <= HighRegNum)
455 Warning(RegLoc, "register not in ascending order in register list");
456 RegList |= 1 << RegNum;
457 HighRegNum = RegNum;
458
Sean Callananb9a25b72010-01-19 20:27:46 +0000459 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000460 }
Sean Callanan18b83232010-01-19 21:44:56 +0000461 const AsmToken &RCurlyTok = Parser.getTok();
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000462 if (RCurlyTok.isNot(AsmToken::RCurly)) {
463 Error(RCurlyTok.getLoc(), "'}' expected");
464 return 0;
465 }
Sean Callanan76264762010-04-02 22:27:05 +0000466 E = RCurlyTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000467 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000468
Chris Lattnerc0ddfaa2010-10-28 17:23:41 +0000469 // FIXME: Need to return an operand!
470 Error(E, "FIXME: register list parsing not implemented");
471 return 0;
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000472}
473
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000474/// Parse an arm memory expression, return false if successful else return true
475/// or an error. The first token must be a '[' when called.
476/// TODO Only preindexing and postindexing addressing are started, unindexed
477/// with option, etc are still to do.
Chris Lattner550276e2010-10-28 20:52:15 +0000478ARMOperand *ARMAsmParser::ParseMemory() {
Sean Callanan76264762010-04-02 22:27:05 +0000479 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000480 assert(Parser.getTok().is(AsmToken::LBrac) &&
Kevin Enderby6bd266e2009-10-12 22:51:49 +0000481 "Token is not an Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +0000482 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000483 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Sean Callanan18b83232010-01-19 21:44:56 +0000485 const AsmToken &BaseRegTok = Parser.getTok();
Chris Lattner550276e2010-10-28 20:52:15 +0000486 if (BaseRegTok.isNot(AsmToken::Identifier)) {
487 Error(BaseRegTok.getLoc(), "register expected");
488 return 0;
489 }
Chris Lattnere5658fa2010-10-30 04:09:10 +0000490 int BaseRegNum = TryParseRegister();
491 if (BaseRegNum == -1) {
Chris Lattner550276e2010-10-28 20:52:15 +0000492 Error(BaseRegTok.getLoc(), "register expected");
493 return 0;
494 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495
496 bool Preindexed = false;
497 bool Postindexed = false;
498 bool OffsetIsReg = false;
499 bool Negative = false;
500 bool Writeback = false;
501
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000502 // First look for preindexed address forms, that is after the "[Rn" we now
503 // have to see if the next token is a comma.
Sean Callanan18b83232010-01-19 21:44:56 +0000504 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000505 if (Tok.is(AsmToken::Comma)) {
506 Preindexed = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000507 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000508 int OffsetRegNum;
509 bool OffsetRegShifted;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000510 enum ShiftType ShiftType;
511 const MCExpr *ShiftAmount;
512 const MCExpr *Offset;
Chris Lattner550276e2010-10-28 20:52:15 +0000513 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
514 Offset, OffsetIsReg, OffsetRegNum, E))
515 return 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000516 const AsmToken &RBracTok = Parser.getTok();
Chris Lattner550276e2010-10-28 20:52:15 +0000517 if (RBracTok.isNot(AsmToken::RBrac)) {
518 Error(RBracTok.getLoc(), "']' expected");
519 return 0;
520 }
Sean Callanan76264762010-04-02 22:27:05 +0000521 E = RBracTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000522 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000523
Sean Callanan18b83232010-01-19 21:44:56 +0000524 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000525 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000526 E = ExclaimTok.getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000527 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000528 Parser.Lex(); // Eat exclaim token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000529 }
Chris Lattner550276e2010-10-28 20:52:15 +0000530 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
531 OffsetRegShifted, ShiftType, ShiftAmount,
532 Preindexed, Postindexed, Negative, Writeback,
533 S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000534 }
535 // The "[Rn" we have so far was not followed by a comma.
536 else if (Tok.is(AsmToken::RBrac)) {
Jim Grosbach80eb2332010-10-29 17:41:25 +0000537 // If there's anything other than the right brace, this is a post indexing
538 // addressing form.
Sean Callanan76264762010-04-02 22:27:05 +0000539 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000540 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000541
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000542 int OffsetRegNum = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000543 bool OffsetRegShifted = false;
544 enum ShiftType ShiftType;
545 const MCExpr *ShiftAmount;
Chris Lattner14b93852010-10-29 00:27:31 +0000546 const MCExpr *Offset = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000547
Sean Callanan18b83232010-01-19 21:44:56 +0000548 const AsmToken &NextTok = Parser.getTok();
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000549 if (NextTok.isNot(AsmToken::EndOfStatement)) {
Jim Grosbach80eb2332010-10-29 17:41:25 +0000550 Postindexed = true;
551 Writeback = true;
Chris Lattner550276e2010-10-28 20:52:15 +0000552 if (NextTok.isNot(AsmToken::Comma)) {
553 Error(NextTok.getLoc(), "',' expected");
554 return 0;
555 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000556 Parser.Lex(); // Eat comma token.
Chris Lattner550276e2010-10-28 20:52:15 +0000557 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
Jim Grosbach16c74252010-10-29 14:46:02 +0000558 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
Chris Lattner550276e2010-10-28 20:52:15 +0000559 E))
560 return 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000561 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000562
Chris Lattner550276e2010-10-28 20:52:15 +0000563 return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
564 OffsetRegShifted, ShiftType, ShiftAmount,
565 Preindexed, Postindexed, Negative, Writeback,
566 S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000567 }
568
Chris Lattner550276e2010-10-28 20:52:15 +0000569 return 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000570}
571
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000572/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
573/// we will parse the following (were +/- means that a plus or minus is
574/// optional):
575/// +/-Rm
576/// +/-Rm, shift
577/// #offset
578/// we return false on success or an error otherwise.
579bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
Sean Callanan76264762010-04-02 22:27:05 +0000580 bool &OffsetRegShifted,
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000581 enum ShiftType &ShiftType,
582 const MCExpr *&ShiftAmount,
583 const MCExpr *&Offset,
584 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +0000585 int &OffsetRegNum,
586 SMLoc &E) {
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000587 Negative = false;
588 OffsetRegShifted = false;
589 OffsetIsReg = false;
590 OffsetRegNum = -1;
Sean Callanan18b83232010-01-19 21:44:56 +0000591 const AsmToken &NextTok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000592 E = NextTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000593 if (NextTok.is(AsmToken::Plus))
Sean Callananb9a25b72010-01-19 20:27:46 +0000594 Parser.Lex(); // Eat plus token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000595 else if (NextTok.is(AsmToken::Minus)) {
596 Negative = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000597 Parser.Lex(); // Eat minus token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000598 }
599 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
Sean Callanan18b83232010-01-19 21:44:56 +0000600 const AsmToken &OffsetRegTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000601 if (OffsetRegTok.is(AsmToken::Identifier)) {
Chris Lattnere5658fa2010-10-30 04:09:10 +0000602 SMLoc CurLoc = OffsetRegTok.getLoc();
603 OffsetRegNum = TryParseRegister();
604 if (OffsetRegNum != -1) {
Chris Lattner550276e2010-10-28 20:52:15 +0000605 OffsetIsReg = true;
Chris Lattnere5658fa2010-10-30 04:09:10 +0000606 E = CurLoc;
Sean Callanan76264762010-04-02 22:27:05 +0000607 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000608 }
Jim Grosbachd4462a52010-11-01 16:44:21 +0000609
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000610 // If we parsed a register as the offset then their can be a shift after that
611 if (OffsetRegNum != -1) {
612 // Look for a comma then a shift
Sean Callanan18b83232010-01-19 21:44:56 +0000613 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000614 if (Tok.is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000615 Parser.Lex(); // Eat comma token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000616
Sean Callanan18b83232010-01-19 21:44:56 +0000617 const AsmToken &Tok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000618 if (ParseShift(ShiftType, ShiftAmount, E))
Duncan Sands34727662010-07-12 08:16:59 +0000619 return Error(Tok.getLoc(), "shift expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000620 OffsetRegShifted = true;
621 }
622 }
623 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
624 // Look for #offset following the "[Rn," or "[Rn],"
Sean Callanan18b83232010-01-19 21:44:56 +0000625 const AsmToken &HashTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000626 if (HashTok.isNot(AsmToken::Hash))
627 return Error(HashTok.getLoc(), "'#' expected");
Jim Grosbach16c74252010-10-29 14:46:02 +0000628
Sean Callananb9a25b72010-01-19 20:27:46 +0000629 Parser.Lex(); // Eat hash token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000630
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000631 if (getParser().ParseExpression(Offset))
632 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000633 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000634 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000635 return false;
636}
637
638/// ParseShift as one of these two:
639/// ( lsl | lsr | asr | ror ) , # shift_amount
640/// rrx
641/// and returns true if it parses a shift otherwise it returns false.
Jim Grosbach16c74252010-10-29 14:46:02 +0000642bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
Sean Callanan76264762010-04-02 22:27:05 +0000643 SMLoc &E) {
Sean Callanan18b83232010-01-19 21:44:56 +0000644 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000645 if (Tok.isNot(AsmToken::Identifier))
646 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +0000647 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000648 if (ShiftName == "lsl" || ShiftName == "LSL")
649 St = Lsl;
650 else if (ShiftName == "lsr" || ShiftName == "LSR")
651 St = Lsr;
652 else if (ShiftName == "asr" || ShiftName == "ASR")
653 St = Asr;
654 else if (ShiftName == "ror" || ShiftName == "ROR")
655 St = Ror;
656 else if (ShiftName == "rrx" || ShiftName == "RRX")
657 St = Rrx;
658 else
659 return true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000660 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000661
662 // Rrx stands alone.
663 if (St == Rrx)
664 return false;
665
666 // Otherwise, there must be a '#' and a shift amount.
Sean Callanan18b83232010-01-19 21:44:56 +0000667 const AsmToken &HashTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000668 if (HashTok.isNot(AsmToken::Hash))
669 return Error(HashTok.getLoc(), "'#' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000670 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000671
672 if (getParser().ParseExpression(ShiftAmount))
673 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000674
675 return false;
676}
677
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000678/// Parse a arm instruction operand. For now this parses the operand regardless
679/// of the mnemonic.
Chris Lattner550276e2010-10-28 20:52:15 +0000680ARMOperand *ARMAsmParser::ParseOperand() {
Sean Callanan76264762010-04-02 22:27:05 +0000681 SMLoc S, E;
Jim Grosbach16c74252010-10-29 14:46:02 +0000682
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000683 switch (getLexer().getKind()) {
684 case AsmToken::Identifier:
Chris Lattnere5658fa2010-10-30 04:09:10 +0000685 if (ARMOperand *Op = TryParseRegisterWithWriteBack())
Chris Lattner550276e2010-10-28 20:52:15 +0000686 return Op;
Jim Grosbach16c74252010-10-29 14:46:02 +0000687
Kevin Enderby515d5092009-10-15 20:48:48 +0000688 // This was not a register so parse other operands that start with an
689 // identifier (like labels) as expressions and create them as immediates.
690 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +0000691 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +0000692 if (getParser().ParseExpression(IdVal))
Chris Lattner550276e2010-10-28 20:52:15 +0000693 return 0;
Sean Callanan76264762010-04-02 22:27:05 +0000694 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Chris Lattner550276e2010-10-28 20:52:15 +0000695 return ARMOperand::CreateImm(IdVal, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000696 case AsmToken::LBrac:
Chris Lattner550276e2010-10-28 20:52:15 +0000697 return ParseMemory();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000698 case AsmToken::LCurly:
Chris Lattner550276e2010-10-28 20:52:15 +0000699 return ParseRegisterList();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000700 case AsmToken::Hash:
Kevin Enderby079469f2009-10-13 23:33:38 +0000701 // #42 -> immediate.
702 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +0000703 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000704 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000705 const MCExpr *ImmVal;
706 if (getParser().ParseExpression(ImmVal))
Chris Lattner550276e2010-10-28 20:52:15 +0000707 return 0;
Sean Callanan76264762010-04-02 22:27:05 +0000708 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Chris Lattner550276e2010-10-28 20:52:15 +0000709 return ARMOperand::CreateImm(ImmVal, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000710 default:
Chris Lattner550276e2010-10-28 20:52:15 +0000711 Error(Parser.getTok().getLoc(), "unexpected token in operand");
712 return 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000713 }
714}
715
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000716/// Parse an arm instruction mnemonic followed by its operands.
Benjamin Kramer38e59892010-07-14 22:38:02 +0000717bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000718 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Daniel Dunbar5747b132010-08-11 06:37:16 +0000719 // Create the leading tokens for the mnemonic, split by '.' characters.
720 size_t Start = 0, Next = Name.find('.');
721 StringRef Head = Name.slice(Start, Next);
722
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000723 // Determine the predicate, if any.
724 //
725 // FIXME: We need a way to check whether a prefix supports predication,
726 // otherwise we will end up with an ambiguity for instructions that happen to
727 // end with a predicate name.
Jim Grosbach3df518e2010-10-29 21:56:51 +0000728 // FIXME: Likewise, some arithmetic instructions have an 's' prefix which
729 // indicates to update the condition codes. Those instructions have an
730 // additional immediate operand which encodes the prefix as reg0 or CPSR.
731 // Just checking for a suffix of 's' definitely creates ambiguities; e.g,
732 // the SMMLS instruction.
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000733 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
734 .Case("eq", ARMCC::EQ)
735 .Case("ne", ARMCC::NE)
736 .Case("hs", ARMCC::HS)
737 .Case("lo", ARMCC::LO)
738 .Case("mi", ARMCC::MI)
739 .Case("pl", ARMCC::PL)
740 .Case("vs", ARMCC::VS)
741 .Case("vc", ARMCC::VC)
742 .Case("hi", ARMCC::HI)
743 .Case("ls", ARMCC::LS)
744 .Case("ge", ARMCC::GE)
745 .Case("lt", ARMCC::LT)
746 .Case("gt", ARMCC::GT)
747 .Case("le", ARMCC::LE)
748 .Case("al", ARMCC::AL)
749 .Default(~0U);
Jim Grosbach16c74252010-10-29 14:46:02 +0000750
Chris Lattnerdba34d82010-10-30 04:35:59 +0000751 if (CC == ~0U ||
752 (CC == ARMCC::LS && (Head == "vmls" || Head == "vnmls"))) {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000753 CC = ARMCC::AL;
Chris Lattnerdba34d82010-10-30 04:35:59 +0000754 } else {
755 Head = Head.slice(0, Head.size() - 2);
Bill Wendling52925b62010-10-29 23:50:21 +0000756 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000757
Chris Lattner3a697562010-10-28 17:20:03 +0000758 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
Jim Grosbach469ebbe2010-11-01 18:11:14 +0000759 // FIXME: Should only add this operand for predicated instructions
Chris Lattner3a697562010-10-28 17:20:03 +0000760 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc));
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000761
762 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +0000763 while (Next != StringRef::npos) {
764 Start = Next;
765 Next = Name.find('.', Start + 1);
766 Head = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000767
Chris Lattner3a697562010-10-28 17:20:03 +0000768 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
Daniel Dunbar5747b132010-08-11 06:37:16 +0000769 }
770
771 // Read the remaining operands.
772 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000773 // Read the first operand.
Chris Lattner550276e2010-10-28 20:52:15 +0000774 if (ARMOperand *Op = ParseOperand())
775 Operands.push_back(Op);
776 else {
Chris Lattnercbf8a982010-09-11 16:18:25 +0000777 Parser.EatToEndOfStatement();
778 return true;
779 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000780
781 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000782 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000783
784 // Parse and remember the operand.
Chris Lattner550276e2010-10-28 20:52:15 +0000785 if (ARMOperand *Op = ParseOperand())
786 Operands.push_back(Op);
787 else {
Chris Lattnercbf8a982010-09-11 16:18:25 +0000788 Parser.EatToEndOfStatement();
789 return true;
790 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000791 }
792 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000793
Chris Lattnercbf8a982010-09-11 16:18:25 +0000794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
795 Parser.EatToEndOfStatement();
Chris Lattner34e53142010-09-08 05:10:46 +0000796 return TokError("unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +0000797 }
Chris Lattner34e53142010-09-08 05:10:46 +0000798 Parser.Lex(); // Consume the EndOfStatement
Chris Lattner98986712010-01-14 22:21:20 +0000799 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000800}
801
Chris Lattnerfa42fad2010-10-28 21:28:01 +0000802bool ARMAsmParser::
803MatchAndEmitInstruction(SMLoc IDLoc,
804 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
805 MCStreamer &Out) {
806 MCInst Inst;
807 unsigned ErrorInfo;
Chris Lattnere73d4f82010-10-28 21:41:58 +0000808 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
809 case Match_Success:
Chris Lattnerfa42fad2010-10-28 21:28:01 +0000810 Out.EmitInstruction(Inst);
811 return false;
Jim Grosbach16c74252010-10-29 14:46:02 +0000812
Chris Lattnere73d4f82010-10-28 21:41:58 +0000813 case Match_MissingFeature:
814 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
815 return true;
816 case Match_InvalidOperand: {
817 SMLoc ErrorLoc = IDLoc;
818 if (ErrorInfo != ~0U) {
819 if (ErrorInfo >= Operands.size())
820 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +0000821
Chris Lattnere73d4f82010-10-28 21:41:58 +0000822 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
823 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
824 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000825
Chris Lattnere73d4f82010-10-28 21:41:58 +0000826 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +0000827 }
Chris Lattnere73d4f82010-10-28 21:41:58 +0000828 case Match_MnemonicFail:
829 return Error(IDLoc, "unrecognized instruction mnemonic");
830 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000831
Eric Christopherc223e2b2010-10-29 09:26:59 +0000832 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +0000833}
834
835
836
Kevin Enderby515d5092009-10-15 20:48:48 +0000837/// ParseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000838bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
839 StringRef IDVal = DirectiveID.getIdentifier();
840 if (IDVal == ".word")
841 return ParseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +0000842 else if (IDVal == ".thumb")
843 return ParseDirectiveThumb(DirectiveID.getLoc());
844 else if (IDVal == ".thumb_func")
845 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
846 else if (IDVal == ".code")
847 return ParseDirectiveCode(DirectiveID.getLoc());
848 else if (IDVal == ".syntax")
849 return ParseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000850 return true;
851}
852
853/// ParseDirectiveWord
854/// ::= .word [ expression (, expression)* ]
855bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
856 if (getLexer().isNot(AsmToken::EndOfStatement)) {
857 for (;;) {
858 const MCExpr *Value;
859 if (getParser().ParseExpression(Value))
860 return true;
861
Chris Lattneraaec2052010-01-19 19:46:13 +0000862 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000863
864 if (getLexer().is(AsmToken::EndOfStatement))
865 break;
Jim Grosbach16c74252010-10-29 14:46:02 +0000866
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000867 // FIXME: Improve diagnostic.
868 if (getLexer().isNot(AsmToken::Comma))
869 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000870 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000871 }
872 }
873
Sean Callananb9a25b72010-01-19 20:27:46 +0000874 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000875 return false;
876}
877
Kevin Enderby515d5092009-10-15 20:48:48 +0000878/// ParseDirectiveThumb
879/// ::= .thumb
880bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
881 if (getLexer().isNot(AsmToken::EndOfStatement))
882 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000883 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000884
885 // TODO: set thumb mode
886 // TODO: tell the MC streamer the mode
887 // getParser().getStreamer().Emit???();
888 return false;
889}
890
891/// ParseDirectiveThumbFunc
892/// ::= .thumbfunc symbol_name
893bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000894 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000895 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
896 return Error(L, "unexpected token in .syntax directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000897 Parser.Lex(); // Consume the identifier token.
Kevin Enderby515d5092009-10-15 20:48:48 +0000898
899 if (getLexer().isNot(AsmToken::EndOfStatement))
900 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000901 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000902
903 // TODO: mark symbol as a thumb symbol
904 // getParser().getStreamer().Emit???();
905 return false;
906}
907
908/// ParseDirectiveSyntax
909/// ::= .syntax unified | divided
910bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000911 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000912 if (Tok.isNot(AsmToken::Identifier))
913 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +0000914 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +0000915 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000916 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000917 else if (Mode == "divided" || Mode == "DIVIDED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000918 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000919 else
920 return Error(L, "unrecognized syntax mode in .syntax directive");
921
922 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000923 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000924 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000925
926 // TODO tell the MC streamer the mode
927 // getParser().getStreamer().Emit???();
928 return false;
929}
930
931/// ParseDirectiveCode
932/// ::= .code 16 | 32
933bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000934 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000935 if (Tok.isNot(AsmToken::Integer))
936 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000937 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +0000938 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +0000939 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000940 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +0000941 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000942 else
943 return Error(L, "invalid operand to .code directive");
944
945 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000946 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000947 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000948
949 // TODO tell the MC streamer the mode
950 // getParser().getStreamer().Emit???();
951 return false;
952}
953
Sean Callanan90b70972010-04-07 20:29:34 +0000954extern "C" void LLVMInitializeARMAsmLexer();
955
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000956/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000957extern "C" void LLVMInitializeARMAsmParser() {
958 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
959 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +0000960 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000961}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000962
Chris Lattner0692ee62010-09-06 19:11:01 +0000963#define GET_REGISTER_MATCHER
964#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000965#include "ARMGenAsmMatcher.inc"