blob: f44470b2c1b514bc5002c7a6efb8a635f5d9e7c1 [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/Compiler.h"
21#include "llvm/Support/SourceMgr.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000022#include "llvm/Support/raw_ostream.h"
Sean Callanan76264762010-04-02 22:27:05 +000023#include "llvm/ADT/OwningPtr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000024#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000025#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/ADT/Twine.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000027using namespace llvm;
28
29namespace {
30struct ARMOperand;
31
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000032// The shift types for register controlled shifts in arm memory addressing
33enum ShiftType {
34 Lsl,
35 Lsr,
36 Asr,
37 Ror,
38 Rrx
39};
40
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000041class ARMAsmParser : public TargetAsmParser {
42 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000043 TargetMachine &TM;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000044
45private:
46 MCAsmParser &getParser() const { return Parser; }
47
48 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
49
50 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
51
52 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
53
Sean Callanan76264762010-04-02 22:27:05 +000054 bool MaybeParseRegister(OwningPtr<ARMOperand> &Op, bool ParseWriteBack);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000055
Sean Callanan76264762010-04-02 22:27:05 +000056 bool ParseRegisterList(OwningPtr<ARMOperand> &Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +000057
Sean Callanan76264762010-04-02 22:27:05 +000058 bool ParseMemory(OwningPtr<ARMOperand> &Op);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000059
Kevin Enderby9c41fa82009-10-30 22:55:57 +000060 bool ParseMemoryOffsetReg(bool &Negative,
61 bool &OffsetRegShifted,
62 enum ShiftType &ShiftType,
63 const MCExpr *&ShiftAmount,
64 const MCExpr *&Offset,
65 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +000066 int &OffsetRegNum,
67 SMLoc &E);
Kevin Enderby9c41fa82009-10-30 22:55:57 +000068
Sean Callanan76264762010-04-02 22:27:05 +000069 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000070
Sean Callanan76264762010-04-02 22:27:05 +000071 bool ParseOperand(OwningPtr<ARMOperand> &Op);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000072
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000073 bool ParseDirectiveWord(unsigned Size, SMLoc L);
74
Kevin Enderby515d5092009-10-15 20:48:48 +000075 bool ParseDirectiveThumb(SMLoc L);
76
77 bool ParseDirectiveThumbFunc(SMLoc L);
78
79 bool ParseDirectiveCode(SMLoc L);
80
81 bool ParseDirectiveSyntax(SMLoc L);
82
Daniel Dunbarf1e29d42010-08-12 00:55:38 +000083 bool MatchInstruction(SMLoc IDLoc,
84 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar4f98f832010-08-12 00:55:32 +000085 MCInst &Inst) {
Chris Lattnerce4a3352010-09-06 22:11:18 +000086 unsigned ErrorInfo;
87 if (MatchInstructionImpl(Operands, Inst, ErrorInfo) == Match_Success)
Daniel Dunbarf1e29d42010-08-12 00:55:38 +000088 return false;
89
90 // FIXME: We should give nicer diagnostics about the exact failure.
91 Error(IDLoc, "unrecognized instruction");
92
93 return true;
Daniel Dunbar4f98f832010-08-12 00:55:32 +000094 }
95
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000096 /// @name Auto-generated Match Functions
97 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +000098
Chris Lattner0692ee62010-09-06 19:11:01 +000099#define GET_ASSEMBLER_HEADER
100#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000101
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000102 /// }
103
104
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000105public:
Daniel Dunbard73ada72010-07-19 00:33:49 +0000106 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
107 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000108
Benjamin Kramer38e59892010-07-14 22:38:02 +0000109 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000110 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000111
112 virtual bool ParseDirective(AsmToken DirectiveID);
113};
114
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000115/// ARMOperand - Instances of this class represent a parsed ARM machine
116/// instruction.
Chris Lattner76593892010-01-14 21:21:40 +0000117struct ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000118private:
119 ARMOperand() {}
120public:
121 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000122 CondCode,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000123 Immediate,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000124 Memory,
125 Register,
126 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000127 } Kind;
128
Sean Callanan76264762010-04-02 22:27:05 +0000129 SMLoc StartLoc, EndLoc;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000130
131 union {
132 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000133 ARMCC::CondCodes Val;
134 } CC;
135
136 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 const char *Data;
138 unsigned Length;
139 } Tok;
140
141 struct {
142 unsigned RegNum;
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000143 bool Writeback;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 } Reg;
145
Kevin Enderbycfe07242009-10-13 22:19:02 +0000146 struct {
147 const MCExpr *Val;
148 } Imm;
Sean Callanan76264762010-04-02 22:27:05 +0000149
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000150 // This is for all forms of ARM address expressions
151 struct {
152 unsigned BaseRegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000153 unsigned OffsetRegNum; // used when OffsetIsReg is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000154 const MCExpr *Offset; // used when OffsetIsReg is false
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000155 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000156 enum ShiftType ShiftType; // used when OffsetRegShifted is true
157 unsigned
158 OffsetRegShifted : 1, // only used when OffsetIsReg is true
159 Preindexed : 1,
160 Postindexed : 1,
161 OffsetIsReg : 1,
162 Negative : 1, // only used when OffsetIsReg is true
163 Writeback : 1;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000164 } Mem;
165
166 };
Sean Callanan76264762010-04-02 22:27:05 +0000167
Chris Lattner14ab39e2010-09-01 16:04:34 +0000168 //ARMOperand(KindTy K, SMLoc S, SMLoc E)
169 // : Kind(K), StartLoc(S), EndLoc(E) {}
Sean Callanan76264762010-04-02 22:27:05 +0000170
171 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
172 Kind = o.Kind;
173 StartLoc = o.StartLoc;
174 EndLoc = o.EndLoc;
175 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000176 case CondCode:
177 CC = o.CC;
178 break;
Sean Callanan76264762010-04-02 22:27:05 +0000179 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000180 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000181 break;
182 case Register:
183 Reg = o.Reg;
184 break;
185 case Immediate:
186 Imm = o.Imm;
187 break;
188 case Memory:
189 Mem = o.Mem;
190 break;
191 }
192 }
193
194 /// getStartLoc - Get the location of the first token of this operand.
195 SMLoc getStartLoc() const { return StartLoc; }
196 /// getEndLoc - Get the location of the last token of this operand.
197 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000198
Daniel Dunbar8462b302010-08-11 06:36:53 +0000199 ARMCC::CondCodes getCondCode() const {
200 assert(Kind == CondCode && "Invalid access!");
201 return CC.Val;
202 }
203
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000204 StringRef getToken() const {
205 assert(Kind == Token && "Invalid access!");
206 return StringRef(Tok.Data, Tok.Length);
207 }
208
209 unsigned getReg() const {
210 assert(Kind == Register && "Invalid access!");
211 return Reg.RegNum;
212 }
213
Kevin Enderbycfe07242009-10-13 22:19:02 +0000214 const MCExpr *getImm() const {
215 assert(Kind == Immediate && "Invalid access!");
216 return Imm.Val;
217 }
218
Daniel Dunbar8462b302010-08-11 06:36:53 +0000219 bool isCondCode() const { return Kind == CondCode; }
220
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000221 bool isImm() const { return Kind == Immediate; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000222
223 bool isReg() const { return Kind == Register; }
224
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000225 bool isToken() const {return Kind == Token; }
226
227 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
228 // Add as immediates when possible.
229 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
230 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
231 else
232 Inst.addOperand(MCOperand::CreateExpr(Expr));
233 }
234
Daniel Dunbar8462b302010-08-11 06:36:53 +0000235 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000236 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000237 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000238 // FIXME: What belongs here?
239 Inst.addOperand(MCOperand::CreateReg(0));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000240 }
241
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000242 void addRegOperands(MCInst &Inst, unsigned N) const {
243 assert(N == 1 && "Invalid number of operands!");
244 Inst.addOperand(MCOperand::CreateReg(getReg()));
245 }
246
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000247 void addImmOperands(MCInst &Inst, unsigned N) const {
248 assert(N == 1 && "Invalid number of operands!");
249 addExpr(Inst, getImm());
250 }
251
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000252 virtual void dump(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000253
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000254 static void CreateCondCode(OwningPtr<ARMOperand> &Op, ARMCC::CondCodes CC,
255 SMLoc S) {
256 Op.reset(new ARMOperand);
257 Op->Kind = CondCode;
258 Op->CC.Val = CC;
259 Op->StartLoc = S;
260 Op->EndLoc = S;
261 }
262
Sean Callanan76264762010-04-02 22:27:05 +0000263 static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
264 SMLoc S) {
265 Op.reset(new ARMOperand);
266 Op->Kind = Token;
267 Op->Tok.Data = Str.data();
268 Op->Tok.Length = Str.size();
269 Op->StartLoc = S;
270 Op->EndLoc = S;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000271 }
272
Sean Callanan76264762010-04-02 22:27:05 +0000273 static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
274 bool Writeback, SMLoc S, SMLoc E) {
275 Op.reset(new ARMOperand);
276 Op->Kind = Register;
277 Op->Reg.RegNum = RegNum;
278 Op->Reg.Writeback = Writeback;
279
280 Op->StartLoc = S;
281 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000282 }
283
Sean Callanan76264762010-04-02 22:27:05 +0000284 static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
285 SMLoc S, SMLoc E) {
286 Op.reset(new ARMOperand);
287 Op->Kind = Immediate;
288 Op->Imm.Val = Val;
289
290 Op->StartLoc = S;
291 Op->EndLoc = E;
Kevin Enderbycfe07242009-10-13 22:19:02 +0000292 }
293
Sean Callanan76264762010-04-02 22:27:05 +0000294 static void CreateMem(OwningPtr<ARMOperand> &Op,
295 unsigned BaseRegNum, bool OffsetIsReg,
296 const MCExpr *Offset, unsigned OffsetRegNum,
297 bool OffsetRegShifted, enum ShiftType ShiftType,
298 const MCExpr *ShiftAmount, bool Preindexed,
299 bool Postindexed, bool Negative, bool Writeback,
300 SMLoc S, SMLoc E) {
301 Op.reset(new ARMOperand);
302 Op->Kind = Memory;
303 Op->Mem.BaseRegNum = BaseRegNum;
304 Op->Mem.OffsetIsReg = OffsetIsReg;
305 Op->Mem.Offset = Offset;
306 Op->Mem.OffsetRegNum = OffsetRegNum;
307 Op->Mem.OffsetRegShifted = OffsetRegShifted;
308 Op->Mem.ShiftType = ShiftType;
309 Op->Mem.ShiftAmount = ShiftAmount;
310 Op->Mem.Preindexed = Preindexed;
311 Op->Mem.Postindexed = Postindexed;
312 Op->Mem.Negative = Negative;
313 Op->Mem.Writeback = Writeback;
314
315 Op->StartLoc = S;
316 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000317 }
318};
319
320} // end anonymous namespace.
321
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000322void ARMOperand::dump(raw_ostream &OS) const {
323 switch (Kind) {
324 case CondCode:
325 OS << ARMCondCodeToString(getCondCode());
326 break;
327 case Immediate:
328 getImm()->print(OS);
329 break;
330 case Memory:
331 OS << "<memory>";
332 break;
333 case Register:
334 OS << "<register " << getReg() << ">";
335 break;
336 case Token:
337 OS << "'" << getToken() << "'";
338 break;
339 }
340}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000341
342/// @name Auto-generated Match Functions
343/// {
344
345static unsigned MatchRegisterName(StringRef Name);
346
347/// }
348
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000349/// Try to parse a register name. The token must be an Identifier when called,
350/// and if it is a register name a Reg operand is created, the token is eaten
351/// and false is returned. Else true is returned and no token is eaten.
352/// TODO this is likely to change to allow different register types and or to
353/// parse for a specific register type.
Sean Callanan76264762010-04-02 22:27:05 +0000354bool ARMAsmParser::MaybeParseRegister
355 (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
356 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000357 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000358 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
359
360 // FIXME: Validate register for the current architecture; we have to do
361 // validation later, so maybe there is no need for this here.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000362 int RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000363
364 RegNum = MatchRegisterName(Tok.getString());
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000365 if (RegNum == -1)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000366 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000367
368 S = Tok.getLoc();
369
Sean Callananb9a25b72010-01-19 20:27:46 +0000370 Parser.Lex(); // Eat identifier token.
Sean Callanan76264762010-04-02 22:27:05 +0000371
372 E = Parser.getTok().getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000373
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000374 bool Writeback = false;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000375 if (ParseWriteBack) {
Sean Callanan18b83232010-01-19 21:44:56 +0000376 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000377 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000378 E = ExclaimTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000379 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000380 Parser.Lex(); // Eat exclaim token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000381 }
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000382 }
383
Sean Callanan76264762010-04-02 22:27:05 +0000384 ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000385
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000386 return false;
387}
388
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000389/// Parse a register list, return false if successful else return true or an
390/// error. The first token must be a '{' when called.
Sean Callanan76264762010-04-02 22:27:05 +0000391bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
392 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000393 assert(Parser.getTok().is(AsmToken::LCurly) &&
Kevin Enderbycfe07242009-10-13 22:19:02 +0000394 "Token is not an Left Curly Brace");
Sean Callanan76264762010-04-02 22:27:05 +0000395 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000396 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000397
Sean Callanan18b83232010-01-19 21:44:56 +0000398 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000399 SMLoc RegLoc = RegTok.getLoc();
400 if (RegTok.isNot(AsmToken::Identifier))
401 return Error(RegLoc, "register expected");
402 int RegNum = MatchRegisterName(RegTok.getString());
403 if (RegNum == -1)
404 return Error(RegLoc, "register expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000405 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000406 unsigned RegList = 1 << RegNum;
407
408 int HighRegNum = RegNum;
409 // TODO ranges like "{Rn-Rm}"
Sean Callanan18b83232010-01-19 21:44:56 +0000410 while (Parser.getTok().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000411 Parser.Lex(); // Eat comma token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000412
Sean Callanan18b83232010-01-19 21:44:56 +0000413 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000414 SMLoc RegLoc = RegTok.getLoc();
415 if (RegTok.isNot(AsmToken::Identifier))
416 return Error(RegLoc, "register expected");
417 int RegNum = MatchRegisterName(RegTok.getString());
418 if (RegNum == -1)
419 return Error(RegLoc, "register expected");
420
421 if (RegList & (1 << RegNum))
422 Warning(RegLoc, "register duplicated in register list");
423 else if (RegNum <= HighRegNum)
424 Warning(RegLoc, "register not in ascending order in register list");
425 RegList |= 1 << RegNum;
426 HighRegNum = RegNum;
427
Sean Callananb9a25b72010-01-19 20:27:46 +0000428 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000429 }
Sean Callanan18b83232010-01-19 21:44:56 +0000430 const AsmToken &RCurlyTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000431 if (RCurlyTok.isNot(AsmToken::RCurly))
432 return Error(RCurlyTok.getLoc(), "'}' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000433 E = RCurlyTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000434 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000435
436 return false;
437}
438
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000439/// Parse an arm memory expression, return false if successful else return true
440/// or an error. The first token must be a '[' when called.
441/// TODO Only preindexing and postindexing addressing are started, unindexed
442/// with option, etc are still to do.
Sean Callanan76264762010-04-02 22:27:05 +0000443bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
444 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000445 assert(Parser.getTok().is(AsmToken::LBrac) &&
Kevin Enderby6bd266e2009-10-12 22:51:49 +0000446 "Token is not an Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +0000447 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000448 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000449
Sean Callanan18b83232010-01-19 21:44:56 +0000450 const AsmToken &BaseRegTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000451 if (BaseRegTok.isNot(AsmToken::Identifier))
452 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000453 if (MaybeParseRegister(Op, false))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000454 return Error(BaseRegTok.getLoc(), "register expected");
Sean Callanan76264762010-04-02 22:27:05 +0000455 int BaseRegNum = Op->getReg();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000456
457 bool Preindexed = false;
458 bool Postindexed = false;
459 bool OffsetIsReg = false;
460 bool Negative = false;
461 bool Writeback = false;
462
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000463 // First look for preindexed address forms, that is after the "[Rn" we now
464 // have to see if the next token is a comma.
Sean Callanan18b83232010-01-19 21:44:56 +0000465 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000466 if (Tok.is(AsmToken::Comma)) {
467 Preindexed = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000468 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000469 int OffsetRegNum;
470 bool OffsetRegShifted;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000471 enum ShiftType ShiftType;
472 const MCExpr *ShiftAmount;
473 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000474 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Sean Callanan76264762010-04-02 22:27:05 +0000475 Offset, OffsetIsReg, OffsetRegNum, E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000476 return true;
Sean Callanan18b83232010-01-19 21:44:56 +0000477 const AsmToken &RBracTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000478 if (RBracTok.isNot(AsmToken::RBrac))
479 return Error(RBracTok.getLoc(), "']' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000480 E = RBracTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000481 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000482
Sean Callanan18b83232010-01-19 21:44:56 +0000483 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000485 E = ExclaimTok.getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000487 Parser.Lex(); // Eat exclaim token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000488 }
Sean Callanan76264762010-04-02 22:27:05 +0000489 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
490 OffsetRegShifted, ShiftType, ShiftAmount,
491 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000492 return false;
493 }
494 // The "[Rn" we have so far was not followed by a comma.
495 else if (Tok.is(AsmToken::RBrac)) {
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000496 // This is a post indexing addressing forms, that is a ']' follows after
497 // the "[Rn".
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000498 Postindexed = true;
499 Writeback = true;
Sean Callanan76264762010-04-02 22:27:05 +0000500 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000501 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000502
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000503 int OffsetRegNum = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000504 bool OffsetRegShifted = false;
505 enum ShiftType ShiftType;
506 const MCExpr *ShiftAmount;
507 const MCExpr *Offset;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000508
Sean Callanan18b83232010-01-19 21:44:56 +0000509 const AsmToken &NextTok = Parser.getTok();
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000510 if (NextTok.isNot(AsmToken::EndOfStatement)) {
511 if (NextTok.isNot(AsmToken::Comma))
Duncan Sands34727662010-07-12 08:16:59 +0000512 return Error(NextTok.getLoc(), "',' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000513 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000514 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
Sean Callanan76264762010-04-02 22:27:05 +0000515 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
516 E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000517 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000518 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000519
Sean Callanan76264762010-04-02 22:27:05 +0000520 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
521 OffsetRegShifted, ShiftType, ShiftAmount,
522 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000523 return false;
524 }
525
526 return true;
527}
528
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000529/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
530/// we will parse the following (were +/- means that a plus or minus is
531/// optional):
532/// +/-Rm
533/// +/-Rm, shift
534/// #offset
535/// we return false on success or an error otherwise.
536bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
Sean Callanan76264762010-04-02 22:27:05 +0000537 bool &OffsetRegShifted,
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000538 enum ShiftType &ShiftType,
539 const MCExpr *&ShiftAmount,
540 const MCExpr *&Offset,
541 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +0000542 int &OffsetRegNum,
543 SMLoc &E) {
544 OwningPtr<ARMOperand> Op;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000545 Negative = false;
546 OffsetRegShifted = false;
547 OffsetIsReg = false;
548 OffsetRegNum = -1;
Sean Callanan18b83232010-01-19 21:44:56 +0000549 const AsmToken &NextTok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000550 E = NextTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000551 if (NextTok.is(AsmToken::Plus))
Sean Callananb9a25b72010-01-19 20:27:46 +0000552 Parser.Lex(); // Eat plus token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000553 else if (NextTok.is(AsmToken::Minus)) {
554 Negative = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000555 Parser.Lex(); // Eat minus token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000556 }
557 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
Sean Callanan18b83232010-01-19 21:44:56 +0000558 const AsmToken &OffsetRegTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000559 if (OffsetRegTok.is(AsmToken::Identifier)) {
560 OffsetIsReg = !MaybeParseRegister(Op, false);
Sean Callanan76264762010-04-02 22:27:05 +0000561 if (OffsetIsReg) {
562 E = Op->getEndLoc();
563 OffsetRegNum = Op->getReg();
564 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000565 }
566 // If we parsed a register as the offset then their can be a shift after that
567 if (OffsetRegNum != -1) {
568 // Look for a comma then a shift
Sean Callanan18b83232010-01-19 21:44:56 +0000569 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000570 if (Tok.is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000571 Parser.Lex(); // Eat comma token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000572
Sean Callanan18b83232010-01-19 21:44:56 +0000573 const AsmToken &Tok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000574 if (ParseShift(ShiftType, ShiftAmount, E))
Duncan Sands34727662010-07-12 08:16:59 +0000575 return Error(Tok.getLoc(), "shift expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000576 OffsetRegShifted = true;
577 }
578 }
579 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
580 // Look for #offset following the "[Rn," or "[Rn],"
Sean Callanan18b83232010-01-19 21:44:56 +0000581 const AsmToken &HashTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000582 if (HashTok.isNot(AsmToken::Hash))
583 return Error(HashTok.getLoc(), "'#' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000584
Sean Callananb9a25b72010-01-19 20:27:46 +0000585 Parser.Lex(); // Eat hash token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000586
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000587 if (getParser().ParseExpression(Offset))
588 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000589 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000590 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000591 return false;
592}
593
594/// ParseShift as one of these two:
595/// ( lsl | lsr | asr | ror ) , # shift_amount
596/// rrx
597/// and returns true if it parses a shift otherwise it returns false.
Sean Callanan76264762010-04-02 22:27:05 +0000598bool ARMAsmParser::ParseShift(ShiftType &St,
599 const MCExpr *&ShiftAmount,
600 SMLoc &E) {
Sean Callanan18b83232010-01-19 21:44:56 +0000601 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000602 if (Tok.isNot(AsmToken::Identifier))
603 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +0000604 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000605 if (ShiftName == "lsl" || ShiftName == "LSL")
606 St = Lsl;
607 else if (ShiftName == "lsr" || ShiftName == "LSR")
608 St = Lsr;
609 else if (ShiftName == "asr" || ShiftName == "ASR")
610 St = Asr;
611 else if (ShiftName == "ror" || ShiftName == "ROR")
612 St = Ror;
613 else if (ShiftName == "rrx" || ShiftName == "RRX")
614 St = Rrx;
615 else
616 return true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000617 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000618
619 // Rrx stands alone.
620 if (St == Rrx)
621 return false;
622
623 // Otherwise, there must be a '#' and a shift amount.
Sean Callanan18b83232010-01-19 21:44:56 +0000624 const AsmToken &HashTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000625 if (HashTok.isNot(AsmToken::Hash))
626 return Error(HashTok.getLoc(), "'#' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000627 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000628
629 if (getParser().ParseExpression(ShiftAmount))
630 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000631
632 return false;
633}
634
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000635/// Parse a arm instruction operand. For now this parses the operand regardless
636/// of the mnemonic.
Sean Callanan76264762010-04-02 22:27:05 +0000637bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
638 SMLoc S, E;
639
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000640 switch (getLexer().getKind()) {
641 case AsmToken::Identifier:
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000642 if (!MaybeParseRegister(Op, true))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000643 return false;
Kevin Enderby515d5092009-10-15 20:48:48 +0000644 // This was not a register so parse other operands that start with an
645 // identifier (like labels) as expressions and create them as immediates.
646 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +0000647 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +0000648 if (getParser().ParseExpression(IdVal))
649 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000650 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
651 ARMOperand::CreateImm(Op, IdVal, S, E);
Kevin Enderby515d5092009-10-15 20:48:48 +0000652 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000653 case AsmToken::LBrac:
Kevin Enderby515d5092009-10-15 20:48:48 +0000654 return ParseMemory(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000655 case AsmToken::LCurly:
Kevin Enderby515d5092009-10-15 20:48:48 +0000656 return ParseRegisterList(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000657 case AsmToken::Hash:
Kevin Enderby079469f2009-10-13 23:33:38 +0000658 // #42 -> immediate.
659 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +0000660 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000661 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000662 const MCExpr *ImmVal;
663 if (getParser().ParseExpression(ImmVal))
Kevin Enderbycfe07242009-10-13 22:19:02 +0000664 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000665 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
666 ARMOperand::CreateImm(Op, ImmVal, S, E);
Kevin Enderbycfe07242009-10-13 22:19:02 +0000667 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000668 default:
Sean Callanan18b83232010-01-19 21:44:56 +0000669 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000670 }
671}
672
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000673/// Parse an arm instruction mnemonic followed by its operands.
Benjamin Kramer38e59892010-07-14 22:38:02 +0000674bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000675 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +0000676 OwningPtr<ARMOperand> Op;
Daniel Dunbar5747b132010-08-11 06:37:16 +0000677
678 // Create the leading tokens for the mnemonic, split by '.' characters.
679 size_t Start = 0, Next = Name.find('.');
680 StringRef Head = Name.slice(Start, Next);
681
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000682 // Determine the predicate, if any.
683 //
684 // FIXME: We need a way to check whether a prefix supports predication,
685 // otherwise we will end up with an ambiguity for instructions that happen to
686 // end with a predicate name.
687 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
688 .Case("eq", ARMCC::EQ)
689 .Case("ne", ARMCC::NE)
690 .Case("hs", ARMCC::HS)
691 .Case("lo", ARMCC::LO)
692 .Case("mi", ARMCC::MI)
693 .Case("pl", ARMCC::PL)
694 .Case("vs", ARMCC::VS)
695 .Case("vc", ARMCC::VC)
696 .Case("hi", ARMCC::HI)
697 .Case("ls", ARMCC::LS)
698 .Case("ge", ARMCC::GE)
699 .Case("lt", ARMCC::LT)
700 .Case("gt", ARMCC::GT)
701 .Case("le", ARMCC::LE)
702 .Case("al", ARMCC::AL)
703 .Default(~0U);
704 if (CC != ~0U) {
705 Head = Head.slice(0, Head.size() - 2);
706 } else
707 CC = ARMCC::AL;
708
Daniel Dunbar5747b132010-08-11 06:37:16 +0000709 ARMOperand::CreateToken(Op, Head, NameLoc);
Sean Callanan76264762010-04-02 22:27:05 +0000710 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000711
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000712 ARMOperand::CreateCondCode(Op, ARMCC::CondCodes(CC), NameLoc);
713 Operands.push_back(Op.take());
714
715 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +0000716 while (Next != StringRef::npos) {
717 Start = Next;
718 Next = Name.find('.', Start + 1);
719 Head = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000720
Daniel Dunbar5747b132010-08-11 06:37:16 +0000721 ARMOperand::CreateToken(Op, Head, NameLoc);
722 Operands.push_back(Op.take());
723 }
724
725 // Read the remaining operands.
726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000727 // Read the first operand.
Sean Callanan76264762010-04-02 22:27:05 +0000728 OwningPtr<ARMOperand> Op;
Chris Lattner98986712010-01-14 22:21:20 +0000729 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000730 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000731
732 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000733 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000734
735 // Parse and remember the operand.
Chris Lattner98986712010-01-14 22:21:20 +0000736 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000737 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000738 }
739 }
Chris Lattner34e53142010-09-08 05:10:46 +0000740
741 if (getLexer().isNot(AsmToken::EndOfStatement))
742 return TokError("unexpected token in argument list");
743 Parser.Lex(); // Consume the EndOfStatement
744
Chris Lattner98986712010-01-14 22:21:20 +0000745 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000746}
747
Kevin Enderby515d5092009-10-15 20:48:48 +0000748/// ParseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000749bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
750 StringRef IDVal = DirectiveID.getIdentifier();
751 if (IDVal == ".word")
752 return ParseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +0000753 else if (IDVal == ".thumb")
754 return ParseDirectiveThumb(DirectiveID.getLoc());
755 else if (IDVal == ".thumb_func")
756 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
757 else if (IDVal == ".code")
758 return ParseDirectiveCode(DirectiveID.getLoc());
759 else if (IDVal == ".syntax")
760 return ParseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000761 return true;
762}
763
764/// ParseDirectiveWord
765/// ::= .word [ expression (, expression)* ]
766bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
768 for (;;) {
769 const MCExpr *Value;
770 if (getParser().ParseExpression(Value))
771 return true;
772
Chris Lattneraaec2052010-01-19 19:46:13 +0000773 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000774
775 if (getLexer().is(AsmToken::EndOfStatement))
776 break;
777
778 // FIXME: Improve diagnostic.
779 if (getLexer().isNot(AsmToken::Comma))
780 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000781 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000782 }
783 }
784
Sean Callananb9a25b72010-01-19 20:27:46 +0000785 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000786 return false;
787}
788
Kevin Enderby515d5092009-10-15 20:48:48 +0000789/// ParseDirectiveThumb
790/// ::= .thumb
791bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
792 if (getLexer().isNot(AsmToken::EndOfStatement))
793 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000794 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000795
796 // TODO: set thumb mode
797 // TODO: tell the MC streamer the mode
798 // getParser().getStreamer().Emit???();
799 return false;
800}
801
802/// ParseDirectiveThumbFunc
803/// ::= .thumbfunc symbol_name
804bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000805 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000806 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
807 return Error(L, "unexpected token in .syntax directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000808 StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
Sean Callananb9a25b72010-01-19 20:27:46 +0000809 Parser.Lex(); // Consume the identifier token.
Kevin Enderby515d5092009-10-15 20:48:48 +0000810
811 if (getLexer().isNot(AsmToken::EndOfStatement))
812 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000813 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000814
815 // TODO: mark symbol as a thumb symbol
816 // getParser().getStreamer().Emit???();
817 return false;
818}
819
820/// ParseDirectiveSyntax
821/// ::= .syntax unified | divided
822bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000823 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000824 if (Tok.isNot(AsmToken::Identifier))
825 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +0000826 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +0000827 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000828 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000829 else if (Mode == "divided" || Mode == "DIVIDED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000830 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000831 else
832 return Error(L, "unrecognized syntax mode in .syntax directive");
833
834 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000835 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000836 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000837
838 // TODO tell the MC streamer the mode
839 // getParser().getStreamer().Emit???();
840 return false;
841}
842
843/// ParseDirectiveCode
844/// ::= .code 16 | 32
845bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000846 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000847 if (Tok.isNot(AsmToken::Integer))
848 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000849 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +0000850 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +0000851 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000852 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +0000853 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000854 else
855 return Error(L, "invalid operand to .code directive");
856
857 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000858 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000859 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000860
861 // TODO tell the MC streamer the mode
862 // getParser().getStreamer().Emit???();
863 return false;
864}
865
Sean Callanan90b70972010-04-07 20:29:34 +0000866extern "C" void LLVMInitializeARMAsmLexer();
867
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000868/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000869extern "C" void LLVMInitializeARMAsmParser() {
870 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
871 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +0000872 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000873}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000874
Chris Lattner0692ee62010-09-06 19:11:01 +0000875#define GET_REGISTER_MATCHER
876#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000877#include "ARMGenAsmMatcher.inc"