blob: b87d45826ad6ce80be439f4d6005f64dcd7fa825 [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"
25#include "llvm/ADT/Twine.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000026using namespace llvm;
27
28namespace {
29struct ARMOperand;
30
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000031// The shift types for register controlled shifts in arm memory addressing
32enum ShiftType {
33 Lsl,
34 Lsr,
35 Asr,
36 Ror,
37 Rrx
38};
39
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000040class ARMAsmParser : public TargetAsmParser {
41 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000042 TargetMachine &TM;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000043
44private:
45 MCAsmParser &getParser() const { return Parser; }
46
47 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
48
49 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
50
51 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
52
Sean Callanan76264762010-04-02 22:27:05 +000053 bool MaybeParseRegister(OwningPtr<ARMOperand> &Op, bool ParseWriteBack);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000054
Sean Callanan76264762010-04-02 22:27:05 +000055 bool ParseRegisterList(OwningPtr<ARMOperand> &Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +000056
Sean Callanan76264762010-04-02 22:27:05 +000057 bool ParseMemory(OwningPtr<ARMOperand> &Op);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000058
Kevin Enderby9c41fa82009-10-30 22:55:57 +000059 bool ParseMemoryOffsetReg(bool &Negative,
60 bool &OffsetRegShifted,
61 enum ShiftType &ShiftType,
62 const MCExpr *&ShiftAmount,
63 const MCExpr *&Offset,
64 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +000065 int &OffsetRegNum,
66 SMLoc &E);
Kevin Enderby9c41fa82009-10-30 22:55:57 +000067
Sean Callanan76264762010-04-02 22:27:05 +000068 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000069
Sean Callanan76264762010-04-02 22:27:05 +000070 bool ParseOperand(OwningPtr<ARMOperand> &Op);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000071
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000072 bool ParseDirectiveWord(unsigned Size, SMLoc L);
73
Kevin Enderby515d5092009-10-15 20:48:48 +000074 bool ParseDirectiveThumb(SMLoc L);
75
76 bool ParseDirectiveThumbFunc(SMLoc L);
77
78 bool ParseDirectiveCode(SMLoc L);
79
80 bool ParseDirectiveSyntax(SMLoc L);
81
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000082 /// @name Auto-generated Match Functions
83 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +000084
85 unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
86
Chris Lattner98986712010-01-14 22:21:20 +000087 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000088 MCInst &Inst);
89
Kevin Enderbya7ba3a82009-10-06 22:26:42 +000090 /// }
91
92
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000093public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000094 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
95 : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000096
Benjamin Kramer38e59892010-07-14 22:38:02 +000097 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000098 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000099
100 virtual bool ParseDirective(AsmToken DirectiveID);
101};
102
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000103/// ARMOperand - Instances of this class represent a parsed ARM machine
104/// instruction.
Chris Lattner76593892010-01-14 21:21:40 +0000105struct ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000106private:
107 ARMOperand() {}
108public:
109 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000110 CondCode,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000111 Immediate,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000112 Memory,
113 Register,
114 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000115 } Kind;
116
Sean Callanan76264762010-04-02 22:27:05 +0000117 SMLoc StartLoc, EndLoc;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000118
119 union {
120 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000121 ARMCC::CondCodes Val;
122 } CC;
123
124 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000125 const char *Data;
126 unsigned Length;
127 } Tok;
128
129 struct {
130 unsigned RegNum;
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000131 bool Writeback;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000132 } Reg;
133
Kevin Enderbycfe07242009-10-13 22:19:02 +0000134 struct {
135 const MCExpr *Val;
136 } Imm;
Sean Callanan76264762010-04-02 22:27:05 +0000137
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000138 // This is for all forms of ARM address expressions
139 struct {
140 unsigned BaseRegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000141 unsigned OffsetRegNum; // used when OffsetIsReg is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000142 const MCExpr *Offset; // used when OffsetIsReg is false
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000144 enum ShiftType ShiftType; // used when OffsetRegShifted is true
145 unsigned
146 OffsetRegShifted : 1, // only used when OffsetIsReg is true
147 Preindexed : 1,
148 Postindexed : 1,
149 OffsetIsReg : 1,
150 Negative : 1, // only used when OffsetIsReg is true
151 Writeback : 1;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000152 } Mem;
153
154 };
Sean Callanan76264762010-04-02 22:27:05 +0000155
156 ARMOperand(KindTy K, SMLoc S, SMLoc E)
157 : Kind(K), StartLoc(S), EndLoc(E) {}
158
159 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
160 Kind = o.Kind;
161 StartLoc = o.StartLoc;
162 EndLoc = o.EndLoc;
163 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000164 case CondCode:
165 CC = o.CC;
166 break;
Sean Callanan76264762010-04-02 22:27:05 +0000167 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000168 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000169 break;
170 case Register:
171 Reg = o.Reg;
172 break;
173 case Immediate:
174 Imm = o.Imm;
175 break;
176 case Memory:
177 Mem = o.Mem;
178 break;
179 }
180 }
181
182 /// getStartLoc - Get the location of the first token of this operand.
183 SMLoc getStartLoc() const { return StartLoc; }
184 /// getEndLoc - Get the location of the last token of this operand.
185 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000186
Daniel Dunbar8462b302010-08-11 06:36:53 +0000187 ARMCC::CondCodes getCondCode() const {
188 assert(Kind == CondCode && "Invalid access!");
189 return CC.Val;
190 }
191
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000192 StringRef getToken() const {
193 assert(Kind == Token && "Invalid access!");
194 return StringRef(Tok.Data, Tok.Length);
195 }
196
197 unsigned getReg() const {
198 assert(Kind == Register && "Invalid access!");
199 return Reg.RegNum;
200 }
201
Kevin Enderbycfe07242009-10-13 22:19:02 +0000202 const MCExpr *getImm() const {
203 assert(Kind == Immediate && "Invalid access!");
204 return Imm.Val;
205 }
206
Daniel Dunbar8462b302010-08-11 06:36:53 +0000207 bool isCondCode() const { return Kind == CondCode; }
208
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000209 bool isImm() const { return Kind == Immediate; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000210
211 bool isReg() const { return Kind == Register; }
212
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000213 bool isToken() const {return Kind == Token; }
214
215 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
216 // Add as immediates when possible.
217 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
218 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
219 else
220 Inst.addOperand(MCOperand::CreateExpr(Expr));
221 }
222
Daniel Dunbar8462b302010-08-11 06:36:53 +0000223 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
224 assert(N == 1 && "Invalid number of operands!");
225 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
226 }
227
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000228 void addRegOperands(MCInst &Inst, unsigned N) const {
229 assert(N == 1 && "Invalid number of operands!");
230 Inst.addOperand(MCOperand::CreateReg(getReg()));
231 }
232
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000233 void addImmOperands(MCInst &Inst, unsigned N) const {
234 assert(N == 1 && "Invalid number of operands!");
235 addExpr(Inst, getImm());
236 }
237
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000238 virtual void dump(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000239
Sean Callanan76264762010-04-02 22:27:05 +0000240 static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
241 SMLoc S) {
242 Op.reset(new ARMOperand);
243 Op->Kind = Token;
244 Op->Tok.Data = Str.data();
245 Op->Tok.Length = Str.size();
246 Op->StartLoc = S;
247 Op->EndLoc = S;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000248 }
249
Sean Callanan76264762010-04-02 22:27:05 +0000250 static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
251 bool Writeback, SMLoc S, SMLoc E) {
252 Op.reset(new ARMOperand);
253 Op->Kind = Register;
254 Op->Reg.RegNum = RegNum;
255 Op->Reg.Writeback = Writeback;
256
257 Op->StartLoc = S;
258 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000259 }
260
Sean Callanan76264762010-04-02 22:27:05 +0000261 static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
262 SMLoc S, SMLoc E) {
263 Op.reset(new ARMOperand);
264 Op->Kind = Immediate;
265 Op->Imm.Val = Val;
266
267 Op->StartLoc = S;
268 Op->EndLoc = E;
Kevin Enderbycfe07242009-10-13 22:19:02 +0000269 }
270
Sean Callanan76264762010-04-02 22:27:05 +0000271 static void CreateMem(OwningPtr<ARMOperand> &Op,
272 unsigned BaseRegNum, bool OffsetIsReg,
273 const MCExpr *Offset, unsigned OffsetRegNum,
274 bool OffsetRegShifted, enum ShiftType ShiftType,
275 const MCExpr *ShiftAmount, bool Preindexed,
276 bool Postindexed, bool Negative, bool Writeback,
277 SMLoc S, SMLoc E) {
278 Op.reset(new ARMOperand);
279 Op->Kind = Memory;
280 Op->Mem.BaseRegNum = BaseRegNum;
281 Op->Mem.OffsetIsReg = OffsetIsReg;
282 Op->Mem.Offset = Offset;
283 Op->Mem.OffsetRegNum = OffsetRegNum;
284 Op->Mem.OffsetRegShifted = OffsetRegShifted;
285 Op->Mem.ShiftType = ShiftType;
286 Op->Mem.ShiftAmount = ShiftAmount;
287 Op->Mem.Preindexed = Preindexed;
288 Op->Mem.Postindexed = Postindexed;
289 Op->Mem.Negative = Negative;
290 Op->Mem.Writeback = Writeback;
291
292 Op->StartLoc = S;
293 Op->EndLoc = E;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000294 }
295};
296
297} // end anonymous namespace.
298
Daniel Dunbarfa315de2010-08-11 06:37:12 +0000299void ARMOperand::dump(raw_ostream &OS) const {
300 switch (Kind) {
301 case CondCode:
302 OS << ARMCondCodeToString(getCondCode());
303 break;
304 case Immediate:
305 getImm()->print(OS);
306 break;
307 case Memory:
308 OS << "<memory>";
309 break;
310 case Register:
311 OS << "<register " << getReg() << ">";
312 break;
313 case Token:
314 OS << "'" << getToken() << "'";
315 break;
316 }
317}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000318
319/// @name Auto-generated Match Functions
320/// {
321
322static unsigned MatchRegisterName(StringRef Name);
323
324/// }
325
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000326/// Try to parse a register name. The token must be an Identifier when called,
327/// and if it is a register name a Reg operand is created, the token is eaten
328/// and false is returned. Else true is returned and no token is eaten.
329/// TODO this is likely to change to allow different register types and or to
330/// parse for a specific register type.
Sean Callanan76264762010-04-02 22:27:05 +0000331bool ARMAsmParser::MaybeParseRegister
332 (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
333 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000334 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000335 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
336
337 // FIXME: Validate register for the current architecture; we have to do
338 // validation later, so maybe there is no need for this here.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000339 int RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000340
341 RegNum = MatchRegisterName(Tok.getString());
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000342 if (RegNum == -1)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000343 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000344
345 S = Tok.getLoc();
346
Sean Callananb9a25b72010-01-19 20:27:46 +0000347 Parser.Lex(); // Eat identifier token.
Sean Callanan76264762010-04-02 22:27:05 +0000348
349 E = Parser.getTok().getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000350
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000351 bool Writeback = false;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000352 if (ParseWriteBack) {
Sean Callanan18b83232010-01-19 21:44:56 +0000353 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000354 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000355 E = ExclaimTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000356 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000357 Parser.Lex(); // Eat exclaim token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000358 }
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000359 }
360
Sean Callanan76264762010-04-02 22:27:05 +0000361 ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
Kevin Enderby99e6d4e2009-10-07 18:01:35 +0000362
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000363 return false;
364}
365
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000366/// Parse a register list, return false if successful else return true or an
367/// error. The first token must be a '{' when called.
Sean Callanan76264762010-04-02 22:27:05 +0000368bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
369 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000370 assert(Parser.getTok().is(AsmToken::LCurly) &&
Kevin Enderbycfe07242009-10-13 22:19:02 +0000371 "Token is not an Left Curly Brace");
Sean Callanan76264762010-04-02 22:27:05 +0000372 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000373 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000374
Sean Callanan18b83232010-01-19 21:44:56 +0000375 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000376 SMLoc RegLoc = RegTok.getLoc();
377 if (RegTok.isNot(AsmToken::Identifier))
378 return Error(RegLoc, "register expected");
379 int RegNum = MatchRegisterName(RegTok.getString());
380 if (RegNum == -1)
381 return Error(RegLoc, "register expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000382 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000383 unsigned RegList = 1 << RegNum;
384
385 int HighRegNum = RegNum;
386 // TODO ranges like "{Rn-Rm}"
Sean Callanan18b83232010-01-19 21:44:56 +0000387 while (Parser.getTok().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000388 Parser.Lex(); // Eat comma token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000389
Sean Callanan18b83232010-01-19 21:44:56 +0000390 const AsmToken &RegTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000391 SMLoc RegLoc = RegTok.getLoc();
392 if (RegTok.isNot(AsmToken::Identifier))
393 return Error(RegLoc, "register expected");
394 int RegNum = MatchRegisterName(RegTok.getString());
395 if (RegNum == -1)
396 return Error(RegLoc, "register expected");
397
398 if (RegList & (1 << RegNum))
399 Warning(RegLoc, "register duplicated in register list");
400 else if (RegNum <= HighRegNum)
401 Warning(RegLoc, "register not in ascending order in register list");
402 RegList |= 1 << RegNum;
403 HighRegNum = RegNum;
404
Sean Callananb9a25b72010-01-19 20:27:46 +0000405 Parser.Lex(); // Eat identifier token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000406 }
Sean Callanan18b83232010-01-19 21:44:56 +0000407 const AsmToken &RCurlyTok = Parser.getTok();
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000408 if (RCurlyTok.isNot(AsmToken::RCurly))
409 return Error(RCurlyTok.getLoc(), "'}' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000410 E = RCurlyTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000411 Parser.Lex(); // Eat left curly brace token.
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000412
413 return false;
414}
415
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000416/// Parse an arm memory expression, return false if successful else return true
417/// or an error. The first token must be a '[' when called.
418/// TODO Only preindexing and postindexing addressing are started, unindexed
419/// with option, etc are still to do.
Sean Callanan76264762010-04-02 22:27:05 +0000420bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
421 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +0000422 assert(Parser.getTok().is(AsmToken::LBrac) &&
Kevin Enderby6bd266e2009-10-12 22:51:49 +0000423 "Token is not an Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +0000424 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000425 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000426
Sean Callanan18b83232010-01-19 21:44:56 +0000427 const AsmToken &BaseRegTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000428 if (BaseRegTok.isNot(AsmToken::Identifier))
429 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000430 if (MaybeParseRegister(Op, false))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000431 return Error(BaseRegTok.getLoc(), "register expected");
Sean Callanan76264762010-04-02 22:27:05 +0000432 int BaseRegNum = Op->getReg();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000433
434 bool Preindexed = false;
435 bool Postindexed = false;
436 bool OffsetIsReg = false;
437 bool Negative = false;
438 bool Writeback = false;
439
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000440 // First look for preindexed address forms, that is after the "[Rn" we now
441 // have to see if the next token is a comma.
Sean Callanan18b83232010-01-19 21:44:56 +0000442 const AsmToken &Tok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000443 if (Tok.is(AsmToken::Comma)) {
444 Preindexed = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000445 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000446 int OffsetRegNum;
447 bool OffsetRegShifted;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000448 enum ShiftType ShiftType;
449 const MCExpr *ShiftAmount;
450 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000451 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Sean Callanan76264762010-04-02 22:27:05 +0000452 Offset, OffsetIsReg, OffsetRegNum, E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000453 return true;
Sean Callanan18b83232010-01-19 21:44:56 +0000454 const AsmToken &RBracTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000455 if (RBracTok.isNot(AsmToken::RBrac))
456 return Error(RBracTok.getLoc(), "']' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000457 E = RBracTok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000458 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000459
Sean Callanan18b83232010-01-19 21:44:56 +0000460 const AsmToken &ExclaimTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000461 if (ExclaimTok.is(AsmToken::Exclaim)) {
Sean Callanan76264762010-04-02 22:27:05 +0000462 E = ExclaimTok.getLoc();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000463 Writeback = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000464 Parser.Lex(); // Eat exclaim token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000465 }
Sean Callanan76264762010-04-02 22:27:05 +0000466 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
467 OffsetRegShifted, ShiftType, ShiftAmount,
468 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000469 return false;
470 }
471 // The "[Rn" we have so far was not followed by a comma.
472 else if (Tok.is(AsmToken::RBrac)) {
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000473 // This is a post indexing addressing forms, that is a ']' follows after
474 // the "[Rn".
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000475 Postindexed = true;
476 Writeback = true;
Sean Callanan76264762010-04-02 22:27:05 +0000477 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000478 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000479
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000480 int OffsetRegNum = 0;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000481 bool OffsetRegShifted = false;
482 enum ShiftType ShiftType;
483 const MCExpr *ShiftAmount;
484 const MCExpr *Offset;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000485
Sean Callanan18b83232010-01-19 21:44:56 +0000486 const AsmToken &NextTok = Parser.getTok();
Kevin Enderbye2a98dd2009-10-15 21:42:45 +0000487 if (NextTok.isNot(AsmToken::EndOfStatement)) {
488 if (NextTok.isNot(AsmToken::Comma))
Duncan Sands34727662010-07-12 08:16:59 +0000489 return Error(NextTok.getLoc(), "',' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000490 Parser.Lex(); // Eat comma token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000491 if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
Sean Callanan76264762010-04-02 22:27:05 +0000492 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
493 E))
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000494 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000496
Sean Callanan76264762010-04-02 22:27:05 +0000497 ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
498 OffsetRegShifted, ShiftType, ShiftAmount,
499 Preindexed, Postindexed, Negative, Writeback, S, E);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000500 return false;
501 }
502
503 return true;
504}
505
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000506/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
507/// we will parse the following (were +/- means that a plus or minus is
508/// optional):
509/// +/-Rm
510/// +/-Rm, shift
511/// #offset
512/// we return false on success or an error otherwise.
513bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
Sean Callanan76264762010-04-02 22:27:05 +0000514 bool &OffsetRegShifted,
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000515 enum ShiftType &ShiftType,
516 const MCExpr *&ShiftAmount,
517 const MCExpr *&Offset,
518 bool &OffsetIsReg,
Sean Callanan76264762010-04-02 22:27:05 +0000519 int &OffsetRegNum,
520 SMLoc &E) {
521 OwningPtr<ARMOperand> Op;
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000522 Negative = false;
523 OffsetRegShifted = false;
524 OffsetIsReg = false;
525 OffsetRegNum = -1;
Sean Callanan18b83232010-01-19 21:44:56 +0000526 const AsmToken &NextTok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000527 E = NextTok.getLoc();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000528 if (NextTok.is(AsmToken::Plus))
Sean Callananb9a25b72010-01-19 20:27:46 +0000529 Parser.Lex(); // Eat plus token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000530 else if (NextTok.is(AsmToken::Minus)) {
531 Negative = true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000532 Parser.Lex(); // Eat minus token
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000533 }
534 // See if there is a register following the "[Rn," or "[Rn]," we have so far.
Sean Callanan18b83232010-01-19 21:44:56 +0000535 const AsmToken &OffsetRegTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000536 if (OffsetRegTok.is(AsmToken::Identifier)) {
537 OffsetIsReg = !MaybeParseRegister(Op, false);
Sean Callanan76264762010-04-02 22:27:05 +0000538 if (OffsetIsReg) {
539 E = Op->getEndLoc();
540 OffsetRegNum = Op->getReg();
541 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000542 }
543 // If we parsed a register as the offset then their can be a shift after that
544 if (OffsetRegNum != -1) {
545 // Look for a comma then a shift
Sean Callanan18b83232010-01-19 21:44:56 +0000546 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000547 if (Tok.is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000548 Parser.Lex(); // Eat comma token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000549
Sean Callanan18b83232010-01-19 21:44:56 +0000550 const AsmToken &Tok = Parser.getTok();
Sean Callanan76264762010-04-02 22:27:05 +0000551 if (ParseShift(ShiftType, ShiftAmount, E))
Duncan Sands34727662010-07-12 08:16:59 +0000552 return Error(Tok.getLoc(), "shift expected");
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000553 OffsetRegShifted = true;
554 }
555 }
556 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
557 // Look for #offset following the "[Rn," or "[Rn],"
Sean Callanan18b83232010-01-19 21:44:56 +0000558 const AsmToken &HashTok = Parser.getTok();
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000559 if (HashTok.isNot(AsmToken::Hash))
560 return Error(HashTok.getLoc(), "'#' expected");
Sean Callanan76264762010-04-02 22:27:05 +0000561
Sean Callananb9a25b72010-01-19 20:27:46 +0000562 Parser.Lex(); // Eat hash token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000563
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000564 if (getParser().ParseExpression(Offset))
565 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000566 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000567 }
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000568 return false;
569}
570
571/// ParseShift as one of these two:
572/// ( lsl | lsr | asr | ror ) , # shift_amount
573/// rrx
574/// and returns true if it parses a shift otherwise it returns false.
Sean Callanan76264762010-04-02 22:27:05 +0000575bool ARMAsmParser::ParseShift(ShiftType &St,
576 const MCExpr *&ShiftAmount,
577 SMLoc &E) {
Sean Callanan18b83232010-01-19 21:44:56 +0000578 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000579 if (Tok.isNot(AsmToken::Identifier))
580 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +0000581 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000582 if (ShiftName == "lsl" || ShiftName == "LSL")
583 St = Lsl;
584 else if (ShiftName == "lsr" || ShiftName == "LSR")
585 St = Lsr;
586 else if (ShiftName == "asr" || ShiftName == "ASR")
587 St = Asr;
588 else if (ShiftName == "ror" || ShiftName == "ROR")
589 St = Ror;
590 else if (ShiftName == "rrx" || ShiftName == "RRX")
591 St = Rrx;
592 else
593 return true;
Sean Callananb9a25b72010-01-19 20:27:46 +0000594 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000595
596 // Rrx stands alone.
597 if (St == Rrx)
598 return false;
599
600 // Otherwise, there must be a '#' and a shift amount.
Sean Callanan18b83232010-01-19 21:44:56 +0000601 const AsmToken &HashTok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000602 if (HashTok.isNot(AsmToken::Hash))
603 return Error(HashTok.getLoc(), "'#' expected");
Sean Callananb9a25b72010-01-19 20:27:46 +0000604 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000605
606 if (getParser().ParseExpression(ShiftAmount))
607 return true;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000608
609 return false;
610}
611
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000612/// Parse a arm instruction operand. For now this parses the operand regardless
613/// of the mnemonic.
Sean Callanan76264762010-04-02 22:27:05 +0000614bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
615 SMLoc S, E;
616
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000617 switch (getLexer().getKind()) {
618 case AsmToken::Identifier:
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000619 if (!MaybeParseRegister(Op, true))
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000620 return false;
Kevin Enderby515d5092009-10-15 20:48:48 +0000621 // This was not a register so parse other operands that start with an
622 // identifier (like labels) as expressions and create them as immediates.
623 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +0000624 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +0000625 if (getParser().ParseExpression(IdVal))
626 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000627 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
628 ARMOperand::CreateImm(Op, IdVal, S, E);
Kevin Enderby515d5092009-10-15 20:48:48 +0000629 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000630 case AsmToken::LBrac:
Kevin Enderby515d5092009-10-15 20:48:48 +0000631 return ParseMemory(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000632 case AsmToken::LCurly:
Kevin Enderby515d5092009-10-15 20:48:48 +0000633 return ParseRegisterList(Op);
Kevin Enderbyd7894f12009-10-09 21:12:28 +0000634 case AsmToken::Hash:
Kevin Enderby079469f2009-10-13 23:33:38 +0000635 // #42 -> immediate.
636 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +0000637 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000638 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000639 const MCExpr *ImmVal;
640 if (getParser().ParseExpression(ImmVal))
Kevin Enderbycfe07242009-10-13 22:19:02 +0000641 return true;
Sean Callanan76264762010-04-02 22:27:05 +0000642 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
643 ARMOperand::CreateImm(Op, ImmVal, S, E);
Kevin Enderbycfe07242009-10-13 22:19:02 +0000644 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000645 default:
Sean Callanan18b83232010-01-19 21:44:56 +0000646 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000647 }
648}
649
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000650/// Parse an arm instruction mnemonic followed by its operands.
Benjamin Kramer38e59892010-07-14 22:38:02 +0000651bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000652 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +0000653 OwningPtr<ARMOperand> Op;
Daniel Dunbar5747b132010-08-11 06:37:16 +0000654
655 // Create the leading tokens for the mnemonic, split by '.' characters.
656 size_t Start = 0, Next = Name.find('.');
657 StringRef Head = Name.slice(Start, Next);
658
659 ARMOperand::CreateToken(Op, Head, NameLoc);
Sean Callanan76264762010-04-02 22:27:05 +0000660 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000661
Daniel Dunbar5747b132010-08-11 06:37:16 +0000662 while (Next != StringRef::npos) {
663 Start = Next;
664 Next = Name.find('.', Start + 1);
665 Head = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000666
Daniel Dunbar5747b132010-08-11 06:37:16 +0000667 ARMOperand::CreateToken(Op, Head, NameLoc);
668 Operands.push_back(Op.take());
669 }
670
671 // Read the remaining operands.
672 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000673 // Read the first operand.
Sean Callanan76264762010-04-02 22:27:05 +0000674 OwningPtr<ARMOperand> Op;
Chris Lattner98986712010-01-14 22:21:20 +0000675 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000676 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000677
678 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000679 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000680
681 // Parse and remember the operand.
Chris Lattner98986712010-01-14 22:21:20 +0000682 if (ParseOperand(Op)) return true;
Sean Callanan76264762010-04-02 22:27:05 +0000683 Operands.push_back(Op.take());
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000684 }
685 }
Chris Lattner98986712010-01-14 22:21:20 +0000686 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000687}
688
Kevin Enderby515d5092009-10-15 20:48:48 +0000689/// ParseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000690bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
691 StringRef IDVal = DirectiveID.getIdentifier();
692 if (IDVal == ".word")
693 return ParseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +0000694 else if (IDVal == ".thumb")
695 return ParseDirectiveThumb(DirectiveID.getLoc());
696 else if (IDVal == ".thumb_func")
697 return ParseDirectiveThumbFunc(DirectiveID.getLoc());
698 else if (IDVal == ".code")
699 return ParseDirectiveCode(DirectiveID.getLoc());
700 else if (IDVal == ".syntax")
701 return ParseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000702 return true;
703}
704
705/// ParseDirectiveWord
706/// ::= .word [ expression (, expression)* ]
707bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
709 for (;;) {
710 const MCExpr *Value;
711 if (getParser().ParseExpression(Value))
712 return true;
713
Chris Lattneraaec2052010-01-19 19:46:13 +0000714 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000715
716 if (getLexer().is(AsmToken::EndOfStatement))
717 break;
718
719 // FIXME: Improve diagnostic.
720 if (getLexer().isNot(AsmToken::Comma))
721 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000722 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000723 }
724 }
725
Sean Callananb9a25b72010-01-19 20:27:46 +0000726 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000727 return false;
728}
729
Kevin Enderby515d5092009-10-15 20:48:48 +0000730/// ParseDirectiveThumb
731/// ::= .thumb
732bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
733 if (getLexer().isNot(AsmToken::EndOfStatement))
734 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000735 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000736
737 // TODO: set thumb mode
738 // TODO: tell the MC streamer the mode
739 // getParser().getStreamer().Emit???();
740 return false;
741}
742
743/// ParseDirectiveThumbFunc
744/// ::= .thumbfunc symbol_name
745bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000746 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000747 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
748 return Error(L, "unexpected token in .syntax directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000749 StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
Sean Callananb9a25b72010-01-19 20:27:46 +0000750 Parser.Lex(); // Consume the identifier token.
Kevin Enderby515d5092009-10-15 20:48:48 +0000751
752 if (getLexer().isNot(AsmToken::EndOfStatement))
753 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000754 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000755
756 // TODO: mark symbol as a thumb symbol
757 // getParser().getStreamer().Emit???();
758 return false;
759}
760
761/// ParseDirectiveSyntax
762/// ::= .syntax unified | divided
763bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000764 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000765 if (Tok.isNot(AsmToken::Identifier))
766 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +0000767 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +0000768 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000769 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000770 else if (Mode == "divided" || Mode == "DIVIDED")
Sean Callananb9a25b72010-01-19 20:27:46 +0000771 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000772 else
773 return Error(L, "unrecognized syntax mode in .syntax directive");
774
775 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000776 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000777 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000778
779 // TODO tell the MC streamer the mode
780 // getParser().getStreamer().Emit???();
781 return false;
782}
783
784/// ParseDirectiveCode
785/// ::= .code 16 | 32
786bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +0000787 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +0000788 if (Tok.isNot(AsmToken::Integer))
789 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +0000790 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +0000791 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +0000792 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +0000793 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +0000794 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000795 else
796 return Error(L, "invalid operand to .code directive");
797
798 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +0000799 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000800 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +0000801
802 // TODO tell the MC streamer the mode
803 // getParser().getStreamer().Emit???();
804 return false;
805}
806
Sean Callanan90b70972010-04-07 20:29:34 +0000807extern "C" void LLVMInitializeARMAsmLexer();
808
Kevin Enderby9c41fa82009-10-30 22:55:57 +0000809/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000810extern "C" void LLVMInitializeARMAsmParser() {
811 RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
812 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +0000813 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000814}
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000815
816#include "ARMGenAsmMatcher.inc"