blob: abaf704fa5e5a83df01c966ad1b6b5c1a74d21a6 [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
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000083 /// @name Auto-generated Match Functions
84 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +000085
86 unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
87
Chris Lattner98986712010-01-14 22:21:20 +000088 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000089 MCInst &Inst);
90
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000091 /// }
92
93
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000094public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000095 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
96 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000097
Benjamin Kramer38e59892010-07-14 22:38:02 +000098 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000099 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000100
101 virtual bool ParseDirective(AsmToken DirectiveID);
102};
103
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000104/// ARMOperand - Instances of this class represent a parsed ARM machine
105/// instruction.
Chris Lattner76593892010-01-14 21:21:40 +0000106struct ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000107private:
108 ARMOperand() {}
109public:
110 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000111 CondCode,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000112 Immediate,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000113 Memory,
114 Register,
115 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000116 } Kind;
117
Sean Callanan76264762010-04-02 22:27:05 +0000118 SMLoc StartLoc, EndLoc;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000119
120 union {
121 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000122 ARMCC::CondCodes Val;
123 } CC;
124
125 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000126 const char *Data;
127 unsigned Length;
128 } Tok;
129
130 struct {
131 unsigned RegNum;
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000132 bool Writeback;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133 } Reg;
134
Kevin Enderbycfe07242009-10-13 22:19:02 +0000135 struct {
136 const MCExpr *Val;
137 } Imm;
Sean Callanan76264762010-04-02 22:27:05 +0000138
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000139 // This is for all forms of ARM address expressions
140 struct {
141 unsigned BaseRegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142 unsigned OffsetRegNum; // used when OffsetIsReg is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000143 const MCExpr *Offset; // used when OffsetIsReg is false
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000145 enum ShiftType ShiftType; // used when OffsetRegShifted is true
146 unsigned
147 OffsetRegShifted : 1, // only used when OffsetIsReg is true
148 Preindexed : 1,
149 Postindexed : 1,
150 OffsetIsReg : 1,
151 Negative : 1, // only used when OffsetIsReg is true
152 Writeback : 1;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000153 } Mem;
154
155 };
Sean Callanan76264762010-04-02 22:27:05 +0000156
157 ARMOperand(KindTy K, SMLoc S, SMLoc E)
158 : Kind(K), StartLoc(S), EndLoc(E) {}
159
160 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
161 Kind = o.Kind;
162 StartLoc = o.StartLoc;
163 EndLoc = o.EndLoc;
164 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000165 case CondCode:
166 CC = o.CC;
167 break;
Sean Callanan76264762010-04-02 22:27:05 +0000168 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000169 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000170 break;
171 case Register:
172 Reg = o.Reg;
173 break;
174 case Immediate:
175 Imm = o.Imm;
176 break;
177 case Memory:
178 Mem = o.Mem;
179 break;
180 }
181 }
182
183 /// getStartLoc - Get the location of the first token of this operand.
184 SMLoc getStartLoc() const { return StartLoc; }
185 /// getEndLoc - Get the location of the last token of this operand.
186 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000187
Daniel Dunbar8462b302010-08-11 06:36:53 +0000188 ARMCC::CondCodes getCondCode() const {
189 assert(Kind == CondCode && "Invalid access!");
190 return CC.Val;
191 }
192
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000193 StringRef getToken() const {
194 assert(Kind == Token && "Invalid access!");
195 return StringRef(Tok.Data, Tok.Length);
196 }
197
198 unsigned getReg() const {
199 assert(Kind == Register && "Invalid access!");
200 return Reg.RegNum;
201 }
202
Kevin Enderbycfe07242009-10-13 22:19:02 +0000203 const MCExpr *getImm() const {
204 assert(Kind == Immediate && "Invalid access!");
205 return Imm.Val;
206 }
207
Daniel Dunbar8462b302010-08-11 06:36:53 +0000208 bool isCondCode() const { return Kind == CondCode; }
209
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000210 bool isImm() const { return Kind == Immediate; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000211
212 bool isReg() const { return Kind == Register; }
213
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000214 bool isToken() const {return Kind == Token; }
215
216 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
217 // Add as immediates when possible.
218 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
219 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
220 else
221 Inst.addOperand(MCOperand::CreateExpr(Expr));
222 }
223
Daniel Dunbar8462b302010-08-11 06:36:53 +0000224 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000225 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000226 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000227 // FIXME: What belongs here?
228 Inst.addOperand(MCOperand::CreateReg(0));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000229 }
230
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000231 void addRegOperands(MCInst &Inst, unsigned N) const {
232 assert(N == 1 && "Invalid number of operands!");
233 Inst.addOperand(MCOperand::CreateReg(getReg()));
234 }
235
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000236 void addImmOperands(MCInst &Inst, unsigned N) const {
237 assert(N == 1 && "Invalid number of operands!");
238 addExpr(Inst, getImm());
239 }
240
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000241 virtual void dump(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000242
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000243 static void CreateCondCode(OwningPtr<ARMOperand> &Op, ARMCC::CondCodes CC,
244 SMLoc S) {
245 Op.reset(new ARMOperand);
246 Op->Kind = CondCode;
247 Op->CC.Val = CC;
248 Op->StartLoc = S;
249 Op->EndLoc = S;
250 }
251
Sean Callanan76264762010-04-02 22:27:05 +0000252 static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
253 SMLoc S) {
254 Op.reset(new ARMOperand);
255 Op->Kind = Token;
256 Op->Tok.Data = Str.data();
257 Op->Tok.Length = Str.size();
258 Op->StartLoc = S;
259 Op->EndLoc = S;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000260 }
261
Sean Callanan76264762010-04-02 22:27:05 +0000262 static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
263 bool Writeback, SMLoc S, SMLoc E) {
264 Op.reset(new ARMOperand);
265 Op->Kind = Register;
266 Op->Reg.RegNum = RegNum;
267 Op->Reg.Writeback = Writeback;
268
269 Op->StartLoc = S;
270 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000271 }
272
Sean Callanan76264762010-04-02 22:27:05 +0000273 static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
274 SMLoc S, SMLoc E) {
275 Op.reset(new ARMOperand);
276 Op->Kind = Immediate;
277 Op->Imm.Val = Val;
278
279 Op->StartLoc = S;
280 Op->EndLoc = E;
Kevin Enderbycfe07242009-10-13 22:19:02 +0000281 }
282
Sean Callanan76264762010-04-02 22:27:05 +0000283 static void CreateMem(OwningPtr<ARMOperand> &Op,
284 unsigned BaseRegNum, bool OffsetIsReg,
285 const MCExpr *Offset, unsigned OffsetRegNum,
286 bool OffsetRegShifted, enum ShiftType ShiftType,
287 const MCExpr *ShiftAmount, bool Preindexed,
288 bool Postindexed, bool Negative, bool Writeback,
289 SMLoc S, SMLoc E) {
290 Op.reset(new ARMOperand);
291 Op->Kind = Memory;
292 Op->Mem.BaseRegNum = BaseRegNum;
293 Op->Mem.OffsetIsReg = OffsetIsReg;
294 Op->Mem.Offset = Offset;
295 Op->Mem.OffsetRegNum = OffsetRegNum;
296 Op->Mem.OffsetRegShifted = OffsetRegShifted;
297 Op->Mem.ShiftType = ShiftType;
298 Op->Mem.ShiftAmount = ShiftAmount;
299 Op->Mem.Preindexed = Preindexed;
300 Op->Mem.Postindexed = Postindexed;
301 Op->Mem.Negative = Negative;
302 Op->Mem.Writeback = Writeback;
303
304 Op->StartLoc = S;
305 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306 }
307};
308
309} // end anonymous namespace.
310
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000311void ARMOperand::dump(raw_ostream &OS) const {
312 switch (Kind) {
313 case CondCode:
314 OS << ARMCondCodeToString(getCondCode());
315 break;
316 case Immediate:
317 getImm()->print(OS);
318 break;
319 case Memory:
320 OS << "<memory>";
321 break;
322 case Register:
323 OS << "<register " << getReg() << ">";
324 break;
325 case Token:
326 OS << "'" << getToken() << "'";
327 break;
328 }
329}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000330
331/// @name Auto-generated Match Functions
332/// {
333
334static unsigned MatchRegisterName(StringRef Name);
335
336/// }
337
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000338/// Try to parse a register name. The token must be an Identifier when called,
339/// and if it is a register name a Reg operand is created, the token is eaten
340/// and false is returned. Else true is returned and no token is eaten.
341/// TODO this is likely to change to allow different register types and or to
342/// parse for a specific register type.
Sean Callanan76264762010-04-02 22:27:05 +0000343bool ARMAsmParser::MaybeParseRegister
344 (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
345 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000346 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000347 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
348
349 // FIXME: Validate register for the current architecture; we have to do
350 // validation later, so maybe there is no need for this here.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000351 int RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000352
353 RegNum = MatchRegisterName(Tok.getString());
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000354 if (RegNum == -1)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000355 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000356
357 S = Tok.getLoc();
358
Sean Callananb9a25b72010-01-19 20:27:46 +0000359 Parser.Lex(); // Eat identifier token.
Sean Callanan76264762010-04-02 22:27:05 +0000360
361 E = Parser.getTok().getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000362
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000363 bool Writeback = false;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000364 if (ParseWriteBack) {
Sean Callanan18b83232010-01-19 21:44:56 +0000365 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000366 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000367 E = ExclaimTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000368 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000369 Parser.Lex(); // Eat exclaim token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000370 }
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000371 }
372
Sean Callanan76264762010-04-02 22:27:05 +0000373 ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000374
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000375 return false;
376}
377
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000378/// Parse a register list, return false if successful else return true or an
379/// error. The first token must be a '{' when called.
Sean Callanan76264762010-04-02 22:27:05 +0000380bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
381 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000382 assert(Parser.getTok().is(AsmToken::LCurly) &&
Kevin Enderbycfe07242009-10-13 22:19:02 +0000383 "Token is not an Left Curly Brace");
Sean Callanan76264762010-04-02 22:27:05 +0000384 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000385 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000386
Sean Callanan18b83232010-01-19 21:44:56 +0000387 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000388 SMLoc RegLoc = RegTok.getLoc();
389 if (RegTok.isNot(AsmToken::Identifier))
390 return Error(RegLoc, "register expected");
391 int RegNum = MatchRegisterName(RegTok.getString());
392 if (RegNum == -1)
393 return Error(RegLoc, "register expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000394 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000395 unsigned RegList = 1 << RegNum;
396
397 int HighRegNum = RegNum;
398 // TODO ranges like "{Rn-Rm}"
Sean Callanan18b83232010-01-19 21:44:56 +0000399 while (Parser.getTok().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000400 Parser.Lex(); // Eat comma token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000401
Sean Callanan18b83232010-01-19 21:44:56 +0000402 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000403 SMLoc RegLoc = RegTok.getLoc();
404 if (RegTok.isNot(AsmToken::Identifier))
405 return Error(RegLoc, "register expected");
406 int RegNum = MatchRegisterName(RegTok.getString());
407 if (RegNum == -1)
408 return Error(RegLoc, "register expected");
409
410 if (RegList & (1 << RegNum))
411 Warning(RegLoc, "register duplicated in register list");
412 else if (RegNum <= HighRegNum)
413 Warning(RegLoc, "register not in ascending order in register list");
414 RegList |= 1 << RegNum;
415 HighRegNum = RegNum;
416
Sean Callananb9a25b72010-01-19 20:27:46 +0000417 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000418 }
Sean Callanan18b83232010-01-19 21:44:56 +0000419 const AsmToken &RCurlyTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000420 if (RCurlyTok.isNot(AsmToken::RCurly))
421 return Error(RCurlyTok.getLoc(), "'}' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000422 E = RCurlyTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000423 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000424
425 return false;
426}
427
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000428/// Parse an arm memory expression, return false if successful else return true
429/// or an error. The first token must be a '[' when called.
430/// TODO Only preindexing and postindexing addressing are started, unindexed
431/// with option, etc are still to do.
Sean Callanan76264762010-04-02 22:27:05 +0000432bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
433 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000434 assert(Parser.getTok().is(AsmToken::LBrac) &&
Kevin Enderby6bd266e2009-10-12 22:51:49 +0000435 "Token is not an Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +0000436 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000437 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000438
Sean Callanan18b83232010-01-19 21:44:56 +0000439 const AsmToken &BaseRegTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000440 if (BaseRegTok.isNot(AsmToken::Identifier))
441 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000442 if (MaybeParseRegister(Op, false))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000443 return Error(BaseRegTok.getLoc(), "register expected");
Sean Callanan76264762010-04-02 22:27:05 +0000444 int BaseRegNum = Op->getReg();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000445
446 bool Preindexed = false;
447 bool Postindexed = false;
448 bool OffsetIsReg = false;
449 bool Negative = false;
450 bool Writeback = false;
451
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000452 // First look for preindexed address forms, that is after the "[Rn" we now
453 // have to see if the next token is a comma.
Sean Callanan18b83232010-01-19 21:44:56 +0000454 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000455 if (Tok.is(AsmToken::Comma)) {
456 Preindexed = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000457 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000458 int OffsetRegNum;
459 bool OffsetRegShifted;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000460 enum ShiftType ShiftType;
461 const MCExpr *ShiftAmount;
462 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000463 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Sean Callanan76264762010-04-02 22:27:05 +0000464 Offset, OffsetIsReg, OffsetRegNum, E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000465 return true;
Sean Callanan18b83232010-01-19 21:44:56 +0000466 const AsmToken &RBracTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000467 if (RBracTok.isNot(AsmToken::RBrac))
468 return Error(RBracTok.getLoc(), "']' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000469 E = RBracTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000470 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000471
Sean Callanan18b83232010-01-19 21:44:56 +0000472 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000473 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000474 E = ExclaimTok.getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000476 Parser.Lex(); // Eat exclaim token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000477 }
Sean Callanan76264762010-04-02 22:27:05 +0000478 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
479 OffsetRegShifted, ShiftType, ShiftAmount,
480 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000481 return false;
482 }
483 // The "[Rn" we have so far was not followed by a comma.
484 else if (Tok.is(AsmToken::RBrac)) {
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000485 // This is a post indexing addressing forms, that is a ']' follows after
486 // the "[Rn".
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 Postindexed = true;
488 Writeback = true;
Sean Callanan76264762010-04-02 22:27:05 +0000489 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000490 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000491
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000492 int OffsetRegNum = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000493 bool OffsetRegShifted = false;
494 enum ShiftType ShiftType;
495 const MCExpr *ShiftAmount;
496 const MCExpr *Offset;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497
Sean Callanan18b83232010-01-19 21:44:56 +0000498 const AsmToken &NextTok = Parser.getTok();
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000499 if (NextTok.isNot(AsmToken::EndOfStatement)) {
500 if (NextTok.isNot(AsmToken::Comma))
Duncan Sands34727662010-07-12 08:16:59 +0000501 return Error(NextTok.getLoc(), "',' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000502 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000503 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
Sean Callanan76264762010-04-02 22:27:05 +0000504 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
505 E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000506 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000507 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000508
Sean Callanan76264762010-04-02 22:27:05 +0000509 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
510 OffsetRegShifted, ShiftType, ShiftAmount,
511 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000512 return false;
513 }
514
515 return true;
516}
517
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000518/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
519/// we will parse the following (were +/- means that a plus or minus is
520/// optional):
521/// +/-Rm
522/// +/-Rm, shift
523/// #offset
524/// we return false on success or an error otherwise.
525bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
Sean Callanan76264762010-04-02 22:27:05 +0000526 bool &OffsetRegShifted,
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000527 enum ShiftType &ShiftType,
528 const MCExpr *&ShiftAmount,
529 const MCExpr *&Offset,
530 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +0000531 int &OffsetRegNum,
532 SMLoc &E) {
533 OwningPtr<ARMOperand> Op;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000534 Negative = false;
535 OffsetRegShifted = false;
536 OffsetIsReg = false;
537 OffsetRegNum = -1;
Sean Callanan18b83232010-01-19 21:44:56 +0000538 const AsmToken &NextTok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000539 E = NextTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000540 if (NextTok.is(AsmToken::Plus))
Sean Callananb9a25b72010-01-19 20:27:46 +0000541 Parser.Lex(); // Eat plus token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000542 else if (NextTok.is(AsmToken::Minus)) {
543 Negative = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000544 Parser.Lex(); // Eat minus token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000545 }
546 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
Sean Callanan18b83232010-01-19 21:44:56 +0000547 const AsmToken &OffsetRegTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000548 if (OffsetRegTok.is(AsmToken::Identifier)) {
549 OffsetIsReg = !MaybeParseRegister(Op, false);
Sean Callanan76264762010-04-02 22:27:05 +0000550 if (OffsetIsReg) {
551 E = Op->getEndLoc();
552 OffsetRegNum = Op->getReg();
553 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000554 }
555 // If we parsed a register as the offset then their can be a shift after that
556 if (OffsetRegNum != -1) {
557 // Look for a comma then a shift
Sean Callanan18b83232010-01-19 21:44:56 +0000558 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000559 if (Tok.is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000560 Parser.Lex(); // Eat comma token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000561
Sean Callanan18b83232010-01-19 21:44:56 +0000562 const AsmToken &Tok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000563 if (ParseShift(ShiftType, ShiftAmount, E))
Duncan Sands34727662010-07-12 08:16:59 +0000564 return Error(Tok.getLoc(), "shift expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000565 OffsetRegShifted = true;
566 }
567 }
568 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
569 // Look for #offset following the "[Rn," or "[Rn],"
Sean Callanan18b83232010-01-19 21:44:56 +0000570 const AsmToken &HashTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000571 if (HashTok.isNot(AsmToken::Hash))
572 return Error(HashTok.getLoc(), "'#' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000573
Sean Callananb9a25b72010-01-19 20:27:46 +0000574 Parser.Lex(); // Eat hash token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000575
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000576 if (getParser().ParseExpression(Offset))
577 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000578 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000579 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000580 return false;
581}
582
583/// ParseShift as one of these two:
584/// ( lsl | lsr | asr | ror ) , # shift_amount
585/// rrx
586/// and returns true if it parses a shift otherwise it returns false.
Sean Callanan76264762010-04-02 22:27:05 +0000587bool ARMAsmParser::ParseShift(ShiftType &St,
588 const MCExpr *&ShiftAmount,
589 SMLoc &E) {
Sean Callanan18b83232010-01-19 21:44:56 +0000590 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000591 if (Tok.isNot(AsmToken::Identifier))
592 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +0000593 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000594 if (ShiftName == "lsl" || ShiftName == "LSL")
595 St = Lsl;
596 else if (ShiftName == "lsr" || ShiftName == "LSR")
597 St = Lsr;
598 else if (ShiftName == "asr" || ShiftName == "ASR")
599 St = Asr;
600 else if (ShiftName == "ror" || ShiftName == "ROR")
601 St = Ror;
602 else if (ShiftName == "rrx" || ShiftName == "RRX")
603 St = Rrx;
604 else
605 return true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000606 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000607
608 // Rrx stands alone.
609 if (St == Rrx)
610 return false;
611
612 // Otherwise, there must be a '#' and a shift amount.
Sean Callanan18b83232010-01-19 21:44:56 +0000613 const AsmToken &HashTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000614 if (HashTok.isNot(AsmToken::Hash))
615 return Error(HashTok.getLoc(), "'#' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000616 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000617
618 if (getParser().ParseExpression(ShiftAmount))
619 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000620
621 return false;
622}
623
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000624/// Parse a arm instruction operand. For now this parses the operand regardless
625/// of the mnemonic.
Sean Callanan76264762010-04-02 22:27:05 +0000626bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
627 SMLoc S, E;
628
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000629 switch (getLexer().getKind()) {
630 case AsmToken::Identifier:
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000631 if (!MaybeParseRegister(Op, true))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000632 return false;
Kevin Enderby515d5092009-10-15 20:48:48 +0000633 // This was not a register so parse other operands that start with an
634 // identifier (like labels) as expressions and create them as immediates.
635 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +0000636 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +0000637 if (getParser().ParseExpression(IdVal))
638 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000639 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
640 ARMOperand::CreateImm(Op, IdVal, S, E);
Kevin Enderby515d5092009-10-15 20:48:48 +0000641 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000642 case AsmToken::LBrac:
Kevin Enderby515d5092009-10-15 20:48:48 +0000643 return ParseMemory(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000644 case AsmToken::LCurly:
Kevin Enderby515d5092009-10-15 20:48:48 +0000645 return ParseRegisterList(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000646 case AsmToken::Hash:
Kevin Enderby079469f2009-10-13 23:33:38 +0000647 // #42 -> immediate.
648 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +0000649 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000650 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000651 const MCExpr *ImmVal;
652 if (getParser().ParseExpression(ImmVal))
Kevin Enderbycfe07242009-10-13 22:19:02 +0000653 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000654 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
655 ARMOperand::CreateImm(Op, ImmVal, S, E);
Kevin Enderbycfe07242009-10-13 22:19:02 +0000656 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000657 default:
Sean Callanan18b83232010-01-19 21:44:56 +0000658 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000659 }
660}
661
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000662/// Parse an arm instruction mnemonic followed by its operands.
Benjamin Kramer38e59892010-07-14 22:38:02 +0000663bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000664 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +0000665 OwningPtr<ARMOperand> Op;
Daniel Dunbar5747b132010-08-11 06:37:16 +0000666
667 // Create the leading tokens for the mnemonic, split by '.' characters.
668 size_t Start = 0, Next = Name.find('.');
669 StringRef Head = Name.slice(Start, Next);
670
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000671 // Determine the predicate, if any.
672 //
673 // FIXME: We need a way to check whether a prefix supports predication,
674 // otherwise we will end up with an ambiguity for instructions that happen to
675 // end with a predicate name.
676 unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
677 .Case("eq", ARMCC::EQ)
678 .Case("ne", ARMCC::NE)
679 .Case("hs", ARMCC::HS)
680 .Case("lo", ARMCC::LO)
681 .Case("mi", ARMCC::MI)
682 .Case("pl", ARMCC::PL)
683 .Case("vs", ARMCC::VS)
684 .Case("vc", ARMCC::VC)
685 .Case("hi", ARMCC::HI)
686 .Case("ls", ARMCC::LS)
687 .Case("ge", ARMCC::GE)
688 .Case("lt", ARMCC::LT)
689 .Case("gt", ARMCC::GT)
690 .Case("le", ARMCC::LE)
691 .Case("al", ARMCC::AL)
692 .Default(~0U);
693 if (CC != ~0U) {
694 Head = Head.slice(0, Head.size() - 2);
695 } else
696 CC = ARMCC::AL;
697
Daniel Dunbar5747b132010-08-11 06:37:16 +0000698 ARMOperand::CreateToken(Op, Head, NameLoc);
Sean Callanan76264762010-04-02 22:27:05 +0000699 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000700
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000701 ARMOperand::CreateCondCode(Op, ARMCC::CondCodes(CC), NameLoc);
702 Operands.push_back(Op.take());
703
704 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +0000705 while (Next != StringRef::npos) {
706 Start = Next;
707 Next = Name.find('.', Start + 1);
708 Head = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000709
Daniel Dunbar5747b132010-08-11 06:37:16 +0000710 ARMOperand::CreateToken(Op, Head, NameLoc);
711 Operands.push_back(Op.take());
712 }
713
714 // Read the remaining operands.
715 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000716 // Read the first operand.
Sean Callanan76264762010-04-02 22:27:05 +0000717 OwningPtr<ARMOperand> Op;
Chris Lattner98986712010-01-14 22:21:20 +0000718 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000719 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000720
721 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000722 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000723
724 // Parse and remember the operand.
Chris Lattner98986712010-01-14 22:21:20 +0000725 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000726 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000727 }
728 }
Chris Lattner98986712010-01-14 22:21:20 +0000729 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000730}
731
Kevin Enderby515d5092009-10-15 20:48:48 +0000732/// ParseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000733bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
734 StringRef IDVal = DirectiveID.getIdentifier();
735 if (IDVal == ".word")
736 return ParseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +0000737 else if (IDVal == ".thumb")
738 return ParseDirectiveThumb(DirectiveID.getLoc());
739 else if (IDVal == ".thumb_func")
740 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
741 else if (IDVal == ".code")
742 return ParseDirectiveCode(DirectiveID.getLoc());
743 else if (IDVal == ".syntax")
744 return ParseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000745 return true;
746}
747
748/// ParseDirectiveWord
749/// ::= .word [ expression (, expression)* ]
750bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
751 if (getLexer().isNot(AsmToken::EndOfStatement)) {
752 for (;;) {
753 const MCExpr *Value;
754 if (getParser().ParseExpression(Value))
755 return true;
756
Chris Lattneraaec2052010-01-19 19:46:13 +0000757 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000758
759 if (getLexer().is(AsmToken::EndOfStatement))
760 break;
761
762 // FIXME: Improve diagnostic.
763 if (getLexer().isNot(AsmToken::Comma))
764 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000765 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000766 }
767 }
768
Sean Callananb9a25b72010-01-19 20:27:46 +0000769 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000770 return false;
771}
772
Kevin Enderby515d5092009-10-15 20:48:48 +0000773/// ParseDirectiveThumb
774/// ::= .thumb
775bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
776 if (getLexer().isNot(AsmToken::EndOfStatement))
777 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000778 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000779
780 // TODO: set thumb mode
781 // TODO: tell the MC streamer the mode
782 // getParser().getStreamer().Emit???();
783 return false;
784}
785
786/// ParseDirectiveThumbFunc
787/// ::= .thumbfunc symbol_name
788bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000789 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000790 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
791 return Error(L, "unexpected token in .syntax directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000792 StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
Sean Callananb9a25b72010-01-19 20:27:46 +0000793 Parser.Lex(); // Consume the identifier token.
Kevin Enderby515d5092009-10-15 20:48:48 +0000794
795 if (getLexer().isNot(AsmToken::EndOfStatement))
796 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000797 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000798
799 // TODO: mark symbol as a thumb symbol
800 // getParser().getStreamer().Emit???();
801 return false;
802}
803
804/// ParseDirectiveSyntax
805/// ::= .syntax unified | divided
806bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000807 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000808 if (Tok.isNot(AsmToken::Identifier))
809 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +0000810 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +0000811 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000812 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000813 else if (Mode == "divided" || Mode == "DIVIDED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000814 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000815 else
816 return Error(L, "unrecognized syntax mode in .syntax directive");
817
818 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000819 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000820 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000821
822 // TODO tell the MC streamer the mode
823 // getParser().getStreamer().Emit???();
824 return false;
825}
826
827/// ParseDirectiveCode
828/// ::= .code 16 | 32
829bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000830 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000831 if (Tok.isNot(AsmToken::Integer))
832 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000833 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +0000834 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +0000835 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000836 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +0000837 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000838 else
839 return Error(L, "invalid operand to .code directive");
840
841 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000842 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000843 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000844
845 // TODO tell the MC streamer the mode
846 // getParser().getStreamer().Emit???();
847 return false;
848}
849
Sean Callanan90b70972010-04-07 20:29:34 +0000850extern "C" void LLVMInitializeARMAsmLexer();
851
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000852/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000853extern "C" void LLVMInitializeARMAsmParser() {
854 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
855 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +0000856 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000857}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000858
859#include "ARMGenAsmMatcher.inc"