blob: 6932afbdb419c12c8b9d54650ae2a271d7b9e7f2 [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 Dunbar4f98f832010-08-12 00:55:32 +000083 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
84 MCInst &Inst) {
85 return MatchInstructionImpl(Operands, Inst);
86 }
87
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000088 /// @name Auto-generated Match Functions
89 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +000090
91 unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
92
Daniel Dunbar4f98f832010-08-12 00:55:32 +000093 bool MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>
94 &Operands,
95 MCInst &Inst);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000096
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000097 /// }
98
99
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000100public:
Daniel Dunbard73ada72010-07-19 00:33:49 +0000101 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
102 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000103
Benjamin Kramer38e59892010-07-14 22:38:02 +0000104 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000105 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000106
107 virtual bool ParseDirective(AsmToken DirectiveID);
108};
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 +0000113private:
114 ARMOperand() {}
115public:
116 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000117 CondCode,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000118 Immediate,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000119 Memory,
120 Register,
121 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000122 } Kind;
123
Sean Callanan76264762010-04-02 22:27:05 +0000124 SMLoc StartLoc, EndLoc;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000125
126 union {
127 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000128 ARMCC::CondCodes Val;
129 } CC;
130
131 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000132 const char *Data;
133 unsigned Length;
134 } Tok;
135
136 struct {
137 unsigned RegNum;
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000138 bool Writeback;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000139 } Reg;
140
Kevin Enderbycfe07242009-10-13 22:19:02 +0000141 struct {
142 const MCExpr *Val;
143 } Imm;
Sean Callanan76264762010-04-02 22:27:05 +0000144
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000145 // This is for all forms of ARM address expressions
146 struct {
147 unsigned BaseRegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000148 unsigned OffsetRegNum; // used when OffsetIsReg is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000149 const MCExpr *Offset; // used when OffsetIsReg is false
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000150 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000151 enum ShiftType ShiftType; // used when OffsetRegShifted is true
152 unsigned
153 OffsetRegShifted : 1, // only used when OffsetIsReg is true
154 Preindexed : 1,
155 Postindexed : 1,
156 OffsetIsReg : 1,
157 Negative : 1, // only used when OffsetIsReg is true
158 Writeback : 1;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000159 } Mem;
160
161 };
Sean Callanan76264762010-04-02 22:27:05 +0000162
163 ARMOperand(KindTy K, SMLoc S, SMLoc E)
164 : Kind(K), StartLoc(S), EndLoc(E) {}
165
166 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
167 Kind = o.Kind;
168 StartLoc = o.StartLoc;
169 EndLoc = o.EndLoc;
170 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000171 case CondCode:
172 CC = o.CC;
173 break;
Sean Callanan76264762010-04-02 22:27:05 +0000174 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000175 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000176 break;
177 case Register:
178 Reg = o.Reg;
179 break;
180 case Immediate:
181 Imm = o.Imm;
182 break;
183 case Memory:
184 Mem = o.Mem;
185 break;
186 }
187 }
188
189 /// getStartLoc - Get the location of the first token of this operand.
190 SMLoc getStartLoc() const { return StartLoc; }
191 /// getEndLoc - Get the location of the last token of this operand.
192 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000193
Daniel Dunbar8462b302010-08-11 06:36:53 +0000194 ARMCC::CondCodes getCondCode() const {
195 assert(Kind == CondCode && "Invalid access!");
196 return CC.Val;
197 }
198
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000199 StringRef getToken() const {
200 assert(Kind == Token && "Invalid access!");
201 return StringRef(Tok.Data, Tok.Length);
202 }
203
204 unsigned getReg() const {
205 assert(Kind == Register && "Invalid access!");
206 return Reg.RegNum;
207 }
208
Kevin Enderbycfe07242009-10-13 22:19:02 +0000209 const MCExpr *getImm() const {
210 assert(Kind == Immediate && "Invalid access!");
211 return Imm.Val;
212 }
213
Daniel Dunbar8462b302010-08-11 06:36:53 +0000214 bool isCondCode() const { return Kind == CondCode; }
215
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000216 bool isImm() const { return Kind == Immediate; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000217
218 bool isReg() const { return Kind == Register; }
219
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000220 bool isToken() const {return Kind == Token; }
221
222 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
223 // Add as immediates when possible.
224 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
225 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
226 else
227 Inst.addOperand(MCOperand::CreateExpr(Expr));
228 }
229
Daniel Dunbar8462b302010-08-11 06:36:53 +0000230 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000231 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000232 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000233 // FIXME: What belongs here?
234 Inst.addOperand(MCOperand::CreateReg(0));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000235 }
236
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000237 void addRegOperands(MCInst &Inst, unsigned N) const {
238 assert(N == 1 && "Invalid number of operands!");
239 Inst.addOperand(MCOperand::CreateReg(getReg()));
240 }
241
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000242 void addImmOperands(MCInst &Inst, unsigned N) const {
243 assert(N == 1 && "Invalid number of operands!");
244 addExpr(Inst, getImm());
245 }
246
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000247 virtual void dump(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000248
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000249 static void CreateCondCode(OwningPtr<ARMOperand> &Op, ARMCC::CondCodes CC,
250 SMLoc S) {
251 Op.reset(new ARMOperand);
252 Op->Kind = CondCode;
253 Op->CC.Val = CC;
254 Op->StartLoc = S;
255 Op->EndLoc = S;
256 }
257
Sean Callanan76264762010-04-02 22:27:05 +0000258 static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
259 SMLoc S) {
260 Op.reset(new ARMOperand);
261 Op->Kind = Token;
262 Op->Tok.Data = Str.data();
263 Op->Tok.Length = Str.size();
264 Op->StartLoc = S;
265 Op->EndLoc = S;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000266 }
267
Sean Callanan76264762010-04-02 22:27:05 +0000268 static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
269 bool Writeback, SMLoc S, SMLoc E) {
270 Op.reset(new ARMOperand);
271 Op->Kind = Register;
272 Op->Reg.RegNum = RegNum;
273 Op->Reg.Writeback = Writeback;
274
275 Op->StartLoc = S;
276 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000277 }
278
Sean Callanan76264762010-04-02 22:27:05 +0000279 static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
280 SMLoc S, SMLoc E) {
281 Op.reset(new ARMOperand);
282 Op->Kind = Immediate;
283 Op->Imm.Val = Val;
284
285 Op->StartLoc = S;
286 Op->EndLoc = E;
Kevin Enderbycfe07242009-10-13 22:19:02 +0000287 }
288
Sean Callanan76264762010-04-02 22:27:05 +0000289 static void CreateMem(OwningPtr<ARMOperand> &Op,
290 unsigned BaseRegNum, bool OffsetIsReg,
291 const MCExpr *Offset, unsigned OffsetRegNum,
292 bool OffsetRegShifted, enum ShiftType ShiftType,
293 const MCExpr *ShiftAmount, bool Preindexed,
294 bool Postindexed, bool Negative, bool Writeback,
295 SMLoc S, SMLoc E) {
296 Op.reset(new ARMOperand);
297 Op->Kind = Memory;
298 Op->Mem.BaseRegNum = BaseRegNum;
299 Op->Mem.OffsetIsReg = OffsetIsReg;
300 Op->Mem.Offset = Offset;
301 Op->Mem.OffsetRegNum = OffsetRegNum;
302 Op->Mem.OffsetRegShifted = OffsetRegShifted;
303 Op->Mem.ShiftType = ShiftType;
304 Op->Mem.ShiftAmount = ShiftAmount;
305 Op->Mem.Preindexed = Preindexed;
306 Op->Mem.Postindexed = Postindexed;
307 Op->Mem.Negative = Negative;
308 Op->Mem.Writeback = Writeback;
309
310 Op->StartLoc = S;
311 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000312 }
313};
314
315} // end anonymous namespace.
316
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000317void ARMOperand::dump(raw_ostream &OS) const {
318 switch (Kind) {
319 case CondCode:
320 OS << ARMCondCodeToString(getCondCode());
321 break;
322 case Immediate:
323 getImm()->print(OS);
324 break;
325 case Memory:
326 OS << "<memory>";
327 break;
328 case Register:
329 OS << "<register " << getReg() << ">";
330 break;
331 case Token:
332 OS << "'" << getToken() << "'";
333 break;
334 }
335}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000336
337/// @name Auto-generated Match Functions
338/// {
339
340static unsigned MatchRegisterName(StringRef Name);
341
342/// }
343
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000344/// Try to parse a register name. The token must be an Identifier when called,
345/// and if it is a register name a Reg operand is created, the token is eaten
346/// and false is returned. Else true is returned and no token is eaten.
347/// TODO this is likely to change to allow different register types and or to
348/// parse for a specific register type.
Sean Callanan76264762010-04-02 22:27:05 +0000349bool ARMAsmParser::MaybeParseRegister
350 (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
351 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000352 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000353 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
354
355 // FIXME: Validate register for the current architecture; we have to do
356 // validation later, so maybe there is no need for this here.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000357 int RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000358
359 RegNum = MatchRegisterName(Tok.getString());
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000360 if (RegNum == -1)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000361 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000362
363 S = Tok.getLoc();
364
Sean Callananb9a25b72010-01-19 20:27:46 +0000365 Parser.Lex(); // Eat identifier token.
Sean Callanan76264762010-04-02 22:27:05 +0000366
367 E = Parser.getTok().getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000368
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000369 bool Writeback = false;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000370 if (ParseWriteBack) {
Sean Callanan18b83232010-01-19 21:44:56 +0000371 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000372 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000373 E = ExclaimTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000374 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000375 Parser.Lex(); // Eat exclaim token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000376 }
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000377 }
378
Sean Callanan76264762010-04-02 22:27:05 +0000379 ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000380
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000381 return false;
382}
383
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000384/// Parse a register list, return false if successful else return true or an
385/// error. The first token must be a '{' when called.
Sean Callanan76264762010-04-02 22:27:05 +0000386bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
387 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000388 assert(Parser.getTok().is(AsmToken::LCurly) &&
Kevin Enderbycfe07242009-10-13 22:19:02 +0000389 "Token is not an Left Curly Brace");
Sean Callanan76264762010-04-02 22:27:05 +0000390 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000391 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000392
Sean Callanan18b83232010-01-19 21:44:56 +0000393 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000394 SMLoc RegLoc = RegTok.getLoc();
395 if (RegTok.isNot(AsmToken::Identifier))
396 return Error(RegLoc, "register expected");
397 int RegNum = MatchRegisterName(RegTok.getString());
398 if (RegNum == -1)
399 return Error(RegLoc, "register expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000400 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000401 unsigned RegList = 1 << RegNum;
402
403 int HighRegNum = RegNum;
404 // TODO ranges like "{Rn-Rm}"
Sean Callanan18b83232010-01-19 21:44:56 +0000405 while (Parser.getTok().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000406 Parser.Lex(); // Eat comma token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000407
Sean Callanan18b83232010-01-19 21:44:56 +0000408 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000409 SMLoc RegLoc = RegTok.getLoc();
410 if (RegTok.isNot(AsmToken::Identifier))
411 return Error(RegLoc, "register expected");
412 int RegNum = MatchRegisterName(RegTok.getString());
413 if (RegNum == -1)
414 return Error(RegLoc, "register expected");
415
416 if (RegList & (1 << RegNum))
417 Warning(RegLoc, "register duplicated in register list");
418 else if (RegNum <= HighRegNum)
419 Warning(RegLoc, "register not in ascending order in register list");
420 RegList |= 1 << RegNum;
421 HighRegNum = RegNum;
422
Sean Callananb9a25b72010-01-19 20:27:46 +0000423 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000424 }
Sean Callanan18b83232010-01-19 21:44:56 +0000425 const AsmToken &RCurlyTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000426 if (RCurlyTok.isNot(AsmToken::RCurly))
427 return Error(RCurlyTok.getLoc(), "'}' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000428 E = RCurlyTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000429 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000430
431 return false;
432}
433
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000434/// Parse an arm memory expression, return false if successful else return true
435/// or an error. The first token must be a '[' when called.
436/// TODO Only preindexing and postindexing addressing are started, unindexed
437/// with option, etc are still to do.
Sean Callanan76264762010-04-02 22:27:05 +0000438bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
439 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000440 assert(Parser.getTok().is(AsmToken::LBrac) &&
Kevin Enderby6bd266e2009-10-12 22:51:49 +0000441 "Token is not an Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +0000442 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000443 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000444
Sean Callanan18b83232010-01-19 21:44:56 +0000445 const AsmToken &BaseRegTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000446 if (BaseRegTok.isNot(AsmToken::Identifier))
447 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000448 if (MaybeParseRegister(Op, false))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000449 return Error(BaseRegTok.getLoc(), "register expected");
Sean Callanan76264762010-04-02 22:27:05 +0000450 int BaseRegNum = Op->getReg();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000451
452 bool Preindexed = false;
453 bool Postindexed = false;
454 bool OffsetIsReg = false;
455 bool Negative = false;
456 bool Writeback = false;
457
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000458 // First look for preindexed address forms, that is after the "[Rn" we now
459 // have to see if the next token is a comma.
Sean Callanan18b83232010-01-19 21:44:56 +0000460 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000461 if (Tok.is(AsmToken::Comma)) {
462 Preindexed = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000463 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000464 int OffsetRegNum;
465 bool OffsetRegShifted;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000466 enum ShiftType ShiftType;
467 const MCExpr *ShiftAmount;
468 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000469 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Sean Callanan76264762010-04-02 22:27:05 +0000470 Offset, OffsetIsReg, OffsetRegNum, E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000471 return true;
Sean Callanan18b83232010-01-19 21:44:56 +0000472 const AsmToken &RBracTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000473 if (RBracTok.isNot(AsmToken::RBrac))
474 return Error(RBracTok.getLoc(), "']' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000475 E = RBracTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000476 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000477
Sean Callanan18b83232010-01-19 21:44:56 +0000478 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000479 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000480 E = ExclaimTok.getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000481 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000482 Parser.Lex(); // Eat exclaim token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000483 }
Sean Callanan76264762010-04-02 22:27:05 +0000484 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
485 OffsetRegShifted, ShiftType, ShiftAmount,
486 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 return false;
488 }
489 // The "[Rn" we have so far was not followed by a comma.
490 else if (Tok.is(AsmToken::RBrac)) {
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000491 // This is a post indexing addressing forms, that is a ']' follows after
492 // the "[Rn".
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000493 Postindexed = true;
494 Writeback = true;
Sean Callanan76264762010-04-02 22:27:05 +0000495 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000496 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000498 int OffsetRegNum = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000499 bool OffsetRegShifted = false;
500 enum ShiftType ShiftType;
501 const MCExpr *ShiftAmount;
502 const MCExpr *Offset;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503
Sean Callanan18b83232010-01-19 21:44:56 +0000504 const AsmToken &NextTok = Parser.getTok();
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000505 if (NextTok.isNot(AsmToken::EndOfStatement)) {
506 if (NextTok.isNot(AsmToken::Comma))
Duncan Sands34727662010-07-12 08:16:59 +0000507 return Error(NextTok.getLoc(), "',' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000508 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000509 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
Sean Callanan76264762010-04-02 22:27:05 +0000510 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
511 E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000512 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000513 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000514
Sean Callanan76264762010-04-02 22:27:05 +0000515 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
516 OffsetRegShifted, ShiftType, ShiftAmount,
517 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000518 return false;
519 }
520
521 return true;
522}
523
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000524/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
525/// we will parse the following (were +/- means that a plus or minus is
526/// optional):
527/// +/-Rm
528/// +/-Rm, shift
529/// #offset
530/// we return false on success or an error otherwise.
531bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
Sean Callanan76264762010-04-02 22:27:05 +0000532 bool &OffsetRegShifted,
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000533 enum ShiftType &ShiftType,
534 const MCExpr *&ShiftAmount,
535 const MCExpr *&Offset,
536 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +0000537 int &OffsetRegNum,
538 SMLoc &E) {
539 OwningPtr<ARMOperand> Op;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000540 Negative = false;
541 OffsetRegShifted = false;
542 OffsetIsReg = false;
543 OffsetRegNum = -1;
Sean Callanan18b83232010-01-19 21:44:56 +0000544 const AsmToken &NextTok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000545 E = NextTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000546 if (NextTok.is(AsmToken::Plus))
Sean Callananb9a25b72010-01-19 20:27:46 +0000547 Parser.Lex(); // Eat plus token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000548 else if (NextTok.is(AsmToken::Minus)) {
549 Negative = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000550 Parser.Lex(); // Eat minus token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000551 }
552 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
Sean Callanan18b83232010-01-19 21:44:56 +0000553 const AsmToken &OffsetRegTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000554 if (OffsetRegTok.is(AsmToken::Identifier)) {
555 OffsetIsReg = !MaybeParseRegister(Op, false);
Sean Callanan76264762010-04-02 22:27:05 +0000556 if (OffsetIsReg) {
557 E = Op->getEndLoc();
558 OffsetRegNum = Op->getReg();
559 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000560 }
561 // If we parsed a register as the offset then their can be a shift after that
562 if (OffsetRegNum != -1) {
563 // Look for a comma then a shift
Sean Callanan18b83232010-01-19 21:44:56 +0000564 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000565 if (Tok.is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000566 Parser.Lex(); // Eat comma token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000567
Sean Callanan18b83232010-01-19 21:44:56 +0000568 const AsmToken &Tok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000569 if (ParseShift(ShiftType, ShiftAmount, E))
Duncan Sands34727662010-07-12 08:16:59 +0000570 return Error(Tok.getLoc(), "shift expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000571 OffsetRegShifted = true;
572 }
573 }
574 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
575 // Look for #offset following the "[Rn," or "[Rn],"
Sean Callanan18b83232010-01-19 21:44:56 +0000576 const AsmToken &HashTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000577 if (HashTok.isNot(AsmToken::Hash))
578 return Error(HashTok.getLoc(), "'#' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000579
Sean Callananb9a25b72010-01-19 20:27:46 +0000580 Parser.Lex(); // Eat hash token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000581
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000582 if (getParser().ParseExpression(Offset))
583 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000584 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000585 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000586 return false;
587}
588
589/// ParseShift as one of these two:
590/// ( lsl | lsr | asr | ror ) , # shift_amount
591/// rrx
592/// and returns true if it parses a shift otherwise it returns false.
Sean Callanan76264762010-04-02 22:27:05 +0000593bool ARMAsmParser::ParseShift(ShiftType &St,
594 const MCExpr *&ShiftAmount,
595 SMLoc &E) {
Sean Callanan18b83232010-01-19 21:44:56 +0000596 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000597 if (Tok.isNot(AsmToken::Identifier))
598 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +0000599 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000600 if (ShiftName == "lsl" || ShiftName == "LSL")
601 St = Lsl;
602 else if (ShiftName == "lsr" || ShiftName == "LSR")
603 St = Lsr;
604 else if (ShiftName == "asr" || ShiftName == "ASR")
605 St = Asr;
606 else if (ShiftName == "ror" || ShiftName == "ROR")
607 St = Ror;
608 else if (ShiftName == "rrx" || ShiftName == "RRX")
609 St = Rrx;
610 else
611 return true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000612 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000613
614 // Rrx stands alone.
615 if (St == Rrx)
616 return false;
617
618 // Otherwise, there must be a '#' and a shift amount.
Sean Callanan18b83232010-01-19 21:44:56 +0000619 const AsmToken &HashTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000620 if (HashTok.isNot(AsmToken::Hash))
621 return Error(HashTok.getLoc(), "'#' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000622 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000623
624 if (getParser().ParseExpression(ShiftAmount))
625 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000626
627 return false;
628}
629
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000630/// Parse a arm instruction operand. For now this parses the operand regardless
631/// of the mnemonic.
Sean Callanan76264762010-04-02 22:27:05 +0000632bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
633 SMLoc S, E;
634
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000635 switch (getLexer().getKind()) {
636 case AsmToken::Identifier:
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000637 if (!MaybeParseRegister(Op, true))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000638 return false;
Kevin Enderby515d5092009-10-15 20:48:48 +0000639 // This was not a register so parse other operands that start with an
640 // identifier (like labels) as expressions and create them as immediates.
641 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +0000642 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +0000643 if (getParser().ParseExpression(IdVal))
644 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000645 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
646 ARMOperand::CreateImm(Op, IdVal, S, E);
Kevin Enderby515d5092009-10-15 20:48:48 +0000647 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000648 case AsmToken::LBrac:
Kevin Enderby515d5092009-10-15 20:48:48 +0000649 return ParseMemory(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000650 case AsmToken::LCurly:
Kevin Enderby515d5092009-10-15 20:48:48 +0000651 return ParseRegisterList(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000652 case AsmToken::Hash:
Kevin Enderby079469f2009-10-13 23:33:38 +0000653 // #42 -> immediate.
654 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +0000655 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000656 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000657 const MCExpr *ImmVal;
658 if (getParser().ParseExpression(ImmVal))
Kevin Enderbycfe07242009-10-13 22:19:02 +0000659 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000660 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
661 ARMOperand::CreateImm(Op, ImmVal, S, E);
Kevin Enderbycfe07242009-10-13 22:19:02 +0000662 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000663 default:
Sean Callanan18b83232010-01-19 21:44:56 +0000664 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000665 }
666}
667
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000668/// Parse an arm instruction mnemonic followed by its operands.
Benjamin Kramer38e59892010-07-14 22:38:02 +0000669bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000670 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +0000671 OwningPtr<ARMOperand> Op;
Daniel Dunbar5747b132010-08-11 06:37:16 +0000672
673 // Create the leading tokens for the mnemonic, split by '.' characters.
674 size_t Start = 0, Next = Name.find('.');
675 StringRef Head = Name.slice(Start, Next);
676
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000677 // Determine the predicate, if any.
678 //
679 // FIXME: We need a way to check whether a prefix supports predication,
680 // otherwise we will end up with an ambiguity for instructions that happen to
681 // end with a predicate name.
682 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
683 .Case("eq", ARMCC::EQ)
684 .Case("ne", ARMCC::NE)
685 .Case("hs", ARMCC::HS)
686 .Case("lo", ARMCC::LO)
687 .Case("mi", ARMCC::MI)
688 .Case("pl", ARMCC::PL)
689 .Case("vs", ARMCC::VS)
690 .Case("vc", ARMCC::VC)
691 .Case("hi", ARMCC::HI)
692 .Case("ls", ARMCC::LS)
693 .Case("ge", ARMCC::GE)
694 .Case("lt", ARMCC::LT)
695 .Case("gt", ARMCC::GT)
696 .Case("le", ARMCC::LE)
697 .Case("al", ARMCC::AL)
698 .Default(~0U);
699 if (CC != ~0U) {
700 Head = Head.slice(0, Head.size() - 2);
701 } else
702 CC = ARMCC::AL;
703
Daniel Dunbar5747b132010-08-11 06:37:16 +0000704 ARMOperand::CreateToken(Op, Head, NameLoc);
Sean Callanan76264762010-04-02 22:27:05 +0000705 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000706
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000707 ARMOperand::CreateCondCode(Op, ARMCC::CondCodes(CC), NameLoc);
708 Operands.push_back(Op.take());
709
710 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +0000711 while (Next != StringRef::npos) {
712 Start = Next;
713 Next = Name.find('.', Start + 1);
714 Head = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000715
Daniel Dunbar5747b132010-08-11 06:37:16 +0000716 ARMOperand::CreateToken(Op, Head, NameLoc);
717 Operands.push_back(Op.take());
718 }
719
720 // Read the remaining operands.
721 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000722 // Read the first operand.
Sean Callanan76264762010-04-02 22:27:05 +0000723 OwningPtr<ARMOperand> Op;
Chris Lattner98986712010-01-14 22:21:20 +0000724 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000725 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000726
727 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000728 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000729
730 // Parse and remember the operand.
Chris Lattner98986712010-01-14 22:21:20 +0000731 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000732 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000733 }
734 }
Chris Lattner98986712010-01-14 22:21:20 +0000735 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000736}
737
Kevin Enderby515d5092009-10-15 20:48:48 +0000738/// ParseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000739bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
740 StringRef IDVal = DirectiveID.getIdentifier();
741 if (IDVal == ".word")
742 return ParseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +0000743 else if (IDVal == ".thumb")
744 return ParseDirectiveThumb(DirectiveID.getLoc());
745 else if (IDVal == ".thumb_func")
746 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
747 else if (IDVal == ".code")
748 return ParseDirectiveCode(DirectiveID.getLoc());
749 else if (IDVal == ".syntax")
750 return ParseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000751 return true;
752}
753
754/// ParseDirectiveWord
755/// ::= .word [ expression (, expression)* ]
756bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
758 for (;;) {
759 const MCExpr *Value;
760 if (getParser().ParseExpression(Value))
761 return true;
762
Chris Lattneraaec2052010-01-19 19:46:13 +0000763 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000764
765 if (getLexer().is(AsmToken::EndOfStatement))
766 break;
767
768 // FIXME: Improve diagnostic.
769 if (getLexer().isNot(AsmToken::Comma))
770 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000771 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000772 }
773 }
774
Sean Callananb9a25b72010-01-19 20:27:46 +0000775 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000776 return false;
777}
778
Kevin Enderby515d5092009-10-15 20:48:48 +0000779/// ParseDirectiveThumb
780/// ::= .thumb
781bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
782 if (getLexer().isNot(AsmToken::EndOfStatement))
783 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000784 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000785
786 // TODO: set thumb mode
787 // TODO: tell the MC streamer the mode
788 // getParser().getStreamer().Emit???();
789 return false;
790}
791
792/// ParseDirectiveThumbFunc
793/// ::= .thumbfunc symbol_name
794bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000795 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000796 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
797 return Error(L, "unexpected token in .syntax directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000798 StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
Sean Callananb9a25b72010-01-19 20:27:46 +0000799 Parser.Lex(); // Consume the identifier token.
Kevin Enderby515d5092009-10-15 20:48:48 +0000800
801 if (getLexer().isNot(AsmToken::EndOfStatement))
802 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000803 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000804
805 // TODO: mark symbol as a thumb symbol
806 // getParser().getStreamer().Emit???();
807 return false;
808}
809
810/// ParseDirectiveSyntax
811/// ::= .syntax unified | divided
812bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000813 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000814 if (Tok.isNot(AsmToken::Identifier))
815 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +0000816 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +0000817 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000818 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000819 else if (Mode == "divided" || Mode == "DIVIDED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000820 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000821 else
822 return Error(L, "unrecognized syntax mode in .syntax directive");
823
824 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000825 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000826 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000827
828 // TODO tell the MC streamer the mode
829 // getParser().getStreamer().Emit???();
830 return false;
831}
832
833/// ParseDirectiveCode
834/// ::= .code 16 | 32
835bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000836 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000837 if (Tok.isNot(AsmToken::Integer))
838 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000839 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +0000840 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +0000841 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000842 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +0000843 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000844 else
845 return Error(L, "invalid operand to .code directive");
846
847 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000848 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000849 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000850
851 // TODO tell the MC streamer the mode
852 // getParser().getStreamer().Emit???();
853 return false;
854}
855
Sean Callanan90b70972010-04-07 20:29:34 +0000856extern "C" void LLVMInitializeARMAsmLexer();
857
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000858/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000859extern "C" void LLVMInitializeARMAsmParser() {
860 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
861 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +0000862 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000863}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000864
865#include "ARMGenAsmMatcher.inc"